【问题标题】:generate all combinations of strings based on template根据模板生成所有字符串组合
【发布时间】:2018-04-16 14:17:12
【问题描述】:

如何根据模板生成所有字符串组合?

例如: -

的模板字符串

“{我|我们}想要 {|2|3|4} {苹果|梨}”

花括号“{...}”标识一个或多个单词,每个单词用“|”分隔。

该类应该使用每个单词组中的每个单词组合生成字符串。

我知道它是有限自动机,也是正则表达式。如何高效生成组合?

例如

G[0][j] [想要] G[1][j] G[2][j]"

G[0] = {I, We}
G[1] = {2, 3, 4}
G[2] = {apples, pears}

首先,生成所有可能的组合 c = [0..1][0..2][0..1]:

000
001
010
011
020
021
100
101
110
111
120    
121

然后对于每个 c 将 G[i][j] 替换为 G[i][c[i]]

【问题讨论】:

  • 这是一种编程语言的工作,而不仅仅是正则表达式。
  • 谷歌它。正则表达式不适用。听起来像嵌套循环。
  • 上面的正则表达式可以保存为有限树,深度优先搜索给出所有可能的字符串
  • 在循环中,C 伪代码类似于pI[] = {'I','We'}; pJ[] = {'' ,'2','3','4'}; pK[] = {'apples','pears'}; for ( i = 0; i < 2; i++ ) { string strI = pI[i]; strI += 'want'; for ( j = 0; j < 4; j++ ) { strJ = strI + pJ[j]; for ( k = 0; k < 2; k++ ) { strK = strJ + pK[k]; print( strK ); } } }
  • @sln 模板是输入(不是常量,只是示例)

标签: regex algorithm combinations


【解决方案1】:

外壳球

$ for q in {I,We}\ want\ {2,3,4}\ {apples,pears}; do echo "$q" ; done
I want 2 apples
I want 2 pears
I want 3 apples
I want 3 pears
I want 4 apples
I want 4 pears
We want 2 apples
We want 2 pears
We want 3 apples
We want 3 pears
We want 4 apples
We want 4 pears

【讨论】:

    【解决方案2】:

    目前我发现的这个问题最实用的解决方案是 Python 模块sre_yield

    sre_yield 的目标是有效地生成 所有 值 匹配给定的正则表达式,或计算可能的匹配 高效。

    我添加的重点。

    将其应用于您陈述的问题:将您的模板制定为正则表达式模式并在 sre_yield 中使用它来获取所有可能的组合或计算可能的匹配,如下所示:

    import sre_yield
    result = set(sre_yield.AllStrings("(I|We) want (|2|3|4) (apples|pears)"))
    result.__len__()
    result
    

    输出:

    16
    {'I want  apples',
     'I want  pears',
     'I want 2 apples',
     'I want 2 pears',
     'I want 3 apples',
     'I want 3 pears',
     'I want 4 apples',
     'I want 4 pears',
     'We want  apples',
     'We want  pears',
     'We want 2 apples',
     'We want 2 pears',
     'We want 3 apples',
     'We want 3 pears',
     'We want 4 apples',
     'We want 4 pears'}
    

    PS:我使用set 来避免重复,而不是项目页面上显示的list。如果这不是您想要的,请使用列表。

    【讨论】:

      【解决方案3】:

      原理是:

      • 正则表达式 -> NFA
      • NFA -> 最小 DFA
      • DFS-遍历 DFA(收集所有字符)

      这个原则被执行,例如在RexLex:

      DeterministicAutomaton dfa = Pattern.compileGenericAutomaton("(I|We) want (2|3|4)? (apples|pears)")
        .toAutomaton(new FromGenericAutomaton.ToMinimalDeterministicAutomaton());
      if (dfa.getProperty().isAcyclic()) {
        for (String s : dfa.getSamples(1000)) {
          System.out.println(s);
        }
      }
      

      【讨论】:

        【解决方案4】:

        将每组字符串 {...} 转换为 string array,这样您就有了 n 个数组。 所以对于"{I|We} want {|2|3|4} {apples|pears}",我们将有 4 个数组。

        将这些数组中的每一个放入另一个数组中。在我的示例中,我将调用 collection

        这是 Java 代码,但它足够简单,您应该能够将其转换为任何语言。我没有测试,但它应该可以工作。

        void makeStrings(String[][] wordSet, ArrayList<String> collection) {
               makeStrings(wordSet, collection, "", 0, 0);
        }
        
        void makeStrings(String[][] wordSet, ArrayList<String> collection, String currString, int x_pos, int y_pos) {
        
            //If there are no more wordsets in the whole set add the string (this means 1 combination is completed)
            if (x_pos >= wordSet.length) {
                collection.add(currString);
                return; 
            }
        
        
                //Else if y_pos is outof bounds (meaning no more words within the smaller set {...} return
            else if (y_pos >= wordSet[x_pos].length) { 
                return;
            } 
        
        
        
            else {
                    //Generate 2 new strings, one to send "vertically " and one "horizontally"
                    //This string accepts the current word at x.y and then moves to the next word subset
                    String combo_x = currString + " " + wordSet[x_pos][y_pos];
                    makeStrings(wordSet, collection, combo_x, x_pos + 1, 0);
        
                    //Create a copy of the string and move to the next string within the same subset
                    String combo_y = currString;
                    makeStrings(wordSet, collection, combo_y, x_pos , y_pos  + 1);
                }
            }
        

        *编辑更正

        【讨论】:

        • 很抱歉格式化有困难。此外,如果您需要索引,您可以生成另一个 String[],它将在添加特定单词时添加当前索引 [y]
        猜你喜欢
        • 2012-05-17
        • 2020-08-18
        • 1970-01-01
        • 1970-01-01
        • 2013-05-09
        • 2012-02-16
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多