我有1,2|3,4
和1|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
不,这不是功课。学校十多年前就结束了。
答案 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);
}
}