C#字符串的排列

时间:2015-01-21 17:29:06

标签: c# string algorithm

我有1,2|3,41|2,3|4之类的字符串,需要从中获取以下排列(作为数组/列表)。

Given 1,2|3,4 need to get 2 strings: 1,2,4 1,3,4

Given 1|2,3|4 need to get 4 strings: 1,3 1,4 2,3 2,4

它基本上是在逗号上拆分,然后如果这些元素有一个管道为每个管道分隔的子元素(其余元素)创建排列。解决方案需要处理带有管道的未知数量元素的一般情况。

对使用标准C#库的任何解决方案感兴趣。

陷入困境,寻找社区的一些想法。我似乎无法通过管道超越元素......它几乎就像一个"展望未来"是需要的东西,或者我需要用剩余的逗号分隔元素完成字符串(其中一些可能有管道,这让我觉得递归,但仍然不能绕过它)。

最终订单无关紧要。逗号和管道分隔的元素是数字(存储字符串),最终的字符串顺序无关紧要1,2,4 = 1,4,2

不,这不是功课。学校十多年前就结束了。

3 个答案:

答案 0 :(得分:3)

我们可以用LINQ以一种奇特的方式做到这一点。首先,我们需要Eric Lippert的CartesianProduct扩展方法:

static IEnumerable<IEnumerable<T>> CartesianProduct<T>( this IEnumerable<IEnumerable<T>> sequences )
{
    IEnumerable<IEnumerable<T>> emptyProduct =
        new[] { Enumerable.Empty<T>() };

    return sequences.Aggregate(
            emptyProduct,
            ( accumulator, sequence ) =>
                from accseq in accumulator
                from item in sequence
                select accseq.Concat( new[] { item } ) );
}

然后我们可以做到:

var a = "1|2,3|4".Split( ',' );
var b = a.Select( x => x.Split( '|' ) );
var res = b.CartesianProduct().Select( x => string.Join( ",", x ) );

我们已经完成了!

答案 1 :(得分:0)

我现在无法想到任何边缘情况,但这适用于您的两个示例:

public IEnumerable<string> GetPermutation(string pattern)
{
    var sets = pattern.Split(',');
    var permutations = new[] { new string[] { } };

    foreach(var set in sets)
    {
        permutations = set.Split('|')
            .SelectMany(s => permutations.Select(x => x.Concat(new [] { s }).ToArray()))
            .ToArray();
    }

    return permutations.Select(x => string.Join(",", x));
}

答案 2 :(得分:0)

看起来LINQ解决方案赢了,至少就简洁性而言。

这是我对普通C#代码问题的第一次尝试。

protected List<string> Results = new List<string>();

void GetPermutations(string s)
{
    Results = new List<string>();
    string[] values = s.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
    GetPermutationsRecursive(String.Empty, values, 0);
}

void GetPermutationsRecursive(string soFar, string[] values, int index)
{
    if (index < values.Length)
    {
        foreach (var y in GetVariations(values[index]))
        {
            string s = String.Format("{0}{1}{2}", soFar, soFar.Length > 0 ? "," : String.Empty, y);
            GetPermutationsRecursive(s, values, index + 1);
        }
    }
    else
    {
        Results.Add(soFar);
    }
}

IEnumerable<string> GetVariations(string s)
{
    int pos = s.IndexOf('|');
    if (pos < 0)
    {
        yield return s;
    }
    else
    {
        yield return s.Substring(0, pos);
        yield return s.Substring(pos + 1);
    }
}