Eric Lippert 提出了一种从任意数量的序列which he blogs about here 生成笛卡尔积的通用方法。
他写了一个扩展方法,如下所示:
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);