Eric Lippert提出了一种通用的方法,可以从任意数量的序列中生成笛卡尔积
他在这里写了相关博客。
他编写了一个扩展方法,如下所示:
public static class Combinations
{
public 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<T>(new[] { item }));
}
}
鉴于扩展方法,可以通过以下方式解决原始问题:
var items = new[] { "a", "b", "c" };
int numInEachSelection = 2;
var combs = Enumerable.Repeat(items, numInEachSelection).CartesianProduct();
foreach (var comb in combs)
Console.WriteLine(string.Join(", ", comb));
请注意,
combs
是一个
IEnumerable<IEnumerable<string>>
类型 - 它是一个枚举序列,每个枚举都代表一种组合。
如果您不需要像那样的通用方法,并且您希望每个组合在一个名为
Item1
和
Item2
的属性中分别表示两个组合项,则最简单的方法是这样的:
var items = new[] { "a", "b", "c" };
var combs = from Item1 in items from Item2 in items select new {Item1, Item2};
foreach (var comb in combs)
Console.WriteLine(comb);