解析字符串并在多个字符串中生成所有可能的组合

时间:2014-01-28 11:43:04

标签: c# regex string combinations

在我的SQL Server数据库中,我存储了表示问题正确解决方案的字符串。在此字符串中,某种格式可用于表示多个正确的解决方案。格式:

possible-text [posibility-1/posibility-2] possible-text

这表明posibility-1或posibility-2是正确的。对于有多少可能性没有限制(例如[pos-1 / pos-2 / pos-3 / ...]是可能的)。 但是,可能性为空,例如:

I am [un/]certain.

这意味着答案可能是“我确定”或“我不确定”。 格式也可以嵌套在句子中,例如:

I am [[un/]certain/[un/]sure].

格式也可以在一个句子中多次出现,例如:

[I am/I'm] [[un/]certain/[/un]sure].

我想要的是生成所有可能的组合。例如。上面的表达式应该返回:

I am uncertain.
I am certain.
I am sure.
I am unsure.
I'm uncertain.
I'm certain.
I'm sure.
I'm unsure.

嵌套没有限制,可能性也没有限制。如果只有一种可能的解决方案,那么它将不具有上述格式。我不知道该怎么做。

我必须用C#写这个。我认为一个可能的解决方案可能是编写一个正则表达式,它可以捕获[/]格式并在列表中返回可能的解决方案(对于每个[] -pair)然后通过在堆栈中遍历它们来生成可能的解决方案风格的方式(某种递归和回溯风格),但我还没有找到有效的解决方案。

我对如何开始这一点感到茫然。如果有人能给我一些关于如何解决这个问题的指示,我会很感激。当我找到一些东西时,我会在这里添加它。

注意:我注意到有很多类似的问题,但是解决方案似乎都特定于特定问题,我认为不适用于我的问题。如果我错了,你还记得以前回答过的可以解决这个问题的问题,你能告诉我吗?提前致谢。

更新:只是为了澄清是否不清楚。代码中的每一行都是可能的输入。所以整行都是输入:

[I am/I'm] [[un/]certain/[/un]sure].

2 个答案:

答案 0 :(得分:2)

这应该有效。我没有打扰优化它或进行错误检查(如果输入字符串格式错误)。

class Program
{
    static IEnumerable<string> Parts(string input, out int i)
    {
        var list = new List<string>();
        int level = 1, start = 1;
        i = 1;
        for (; i < input.Length && level > 0; i++)
        {
            if (input[i] == '[')
                level++;
            else if (input[i] == ']')
                level--;

            if (input[i] == '/' && level == 1 || input[i] == ']' && level == 0)
            {
                if (start == i)
                    list.Add(string.Empty);
                else
                    list.Add(input.Substring(start, i - start));
                start = i + 1;
            }
        }
        return list;
    }

    static IEnumerable<string> Combinations(string input, string current = "")
    {
        if (input == string.Empty)
        {
            if (current.Contains('['))
                return Combinations(current, string.Empty);
            return new List<string> { current };
        }
        else if (input[0] == '[')
        {
            int end;
            var parts = Parts(input, out end);
            return parts.SelectMany(x => Combinations(input.Substring(end, input.Length - end), current + x)).ToList();
        }
        else
            return Combinations(input.Substring(1, input.Length - 1), current + input[0]);
    }

    static void Main(string[] args)
    {
        string s = "[I am/I'm] [[un/]certain/[/un]sure].";
        var list = Combinations(s);
    }
}

答案 1 :(得分:1)

您应该创建一个逐字符读取的解析器,并构建一个句子的逻辑树。拥有树时,很容易生成所有可能的组合。您可以使用几种词法解析器,例如ANTLR:http://programming-pages.com/2012/06/28/antlr-with-c-a-simple-grammar/