创建n * m值的所有组合

时间:2011-04-15 10:37:59

标签: c# linq

假设我有IEnumerable<IEnumerable<object>>这样的数据结构:

{
    { A, B }
    { 1, 2, 3 }
    { Z }
}

外部数组可以包含任意数量的内部数组。并且内部数组可以各自独立地包含任意数量的元素。并且为了简单起见,假设没有数组是空的。

我希望将其转换为IEnumerable<IEnumerable<object>>,如下所示:

{ { A, 1, Z }, { A, 2, Z }, { A, 3, Z }, { B, 1, Z }, { B, 2, Z }, { B, 3, Z } }

其中包含原始结构中值的每个组合。因此,每个内部数组中的每个元素都通过索引映射到原始外部数组中的元素/数组。

在C#中最简单的方法是什么?

2 个答案:

答案 0 :(得分:21)

您可以使用Eric Lippert的CartesianProduct方法(摘自here):

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}));                
}

答案 1 :(得分:2)

private static IEnumerable<IEnumerable<object>> GetAllCombinations(IEnumerable<IEnumerable<object>> a)
    {
        if (!a.Skip(1).Any())
        {
            return a.First().Select(x => new[] { x });
        }

        var tail = GetAllCombinations(a.Skip(1)).ToArray();
        return a.First().SelectMany(f => tail.Select(x => new[] { f }.Concat(x)));
    }