在LINQ中为n个集合生成排列

时间:2011-05-20 15:33:16

标签: arrays linq ienumerable permutation combinations

我有一个IEnumerable(IEnumerable [])数组,并希望在这些IEnumerables中生成所有可能的元素组合。 它类似于这个问题:Generating Permutations using LINQ 但是我不知道我预先会有多少IEnumerables,因此不能使用描述的LINQ语句。

举个例子: 我的阵列

IEnumerable[] array;

有例如这些元素

array[0]={0,1,2};
array[1]={a,b};

然后我想要退回这些:

{{0,a},{0,b},{1,a},{1,b},{2,a},{2,b}}

但也可能有:

array[0]={0,1,2};
array[1]={a,b};
array[2]={w,x,y,z};

然后我需要适当的排列。我没有关于有多少IEnumerables的信息,也没有关于每个IEnumerable包含多少元素的信息。

提前感谢您的帮助,

拉​​斯

2 个答案:

答案 0 :(得分:0)

尝试这个方向(你需要修改,我确定,我还没有编译它,所以可能会有一些语法错误)

public IEnumerable<string> CompileCominations
    (IEnumberable<string[]> arrays, List<string> combinations)
{
    if(combinations == null) combinations = new List<string>();
    for(int i = arrays.Count() - 1; i >= 0; i--)
    {
       if(combinations.Count >= 1) combinations = 
           Combine2Lists(combinations, arrays[i]);
       else 
       {
           combinations = Combine2Lists(arrays[i], arrays[i -1];
           i--;
       }
    }
    return combinations;
}

private List<string> Combine2Lists
    (IEnumberable<string> list1, IEnumerable<string> list2)
{
    List<string> currentList = new List<string>();
    for(int i = 0; i < list1.Count(); i ++)
    {
        for(int j = 0; j < list2.Count(); j++)
        {
            currentList.Add(
              string.Format("{0},{1}", list1[i], list2[j]);
        }
    }
    return currentList;
}

同样,未编译,但 应该做的是继续将“item1,item2”添加到列表中,其中item1 =旧的“item1,item2”和item2 =只是新条目来自第n个数组。

因此字符串数组[a,b,c] +字符串数组[1,2,3,4]应该产生:{a, 1}, {a, 2}, {a, 3}, {a, 4}, {b, 1}...并将字符串数组[x,y,z]添加到第一个然后收益率:{a, 1, x}, {a, 1, y}, {a, 1, z}等等。

答案 1 :(得分:0)

好像你想要Cartesian_product。这应该有用,虽然我没有特别仔细地看边缘情况

public static IEnumerable<T> Drop<T>(IEnumerable<T> list, long numToDrop)
{
    if (numToDrop < 0) { throw new ArgumentException("Number to drop must be non-negative"); }
    long dropped = 0;
    var iter = list.GetEnumerator();
    while (dropped < numToDrop && iter.MoveNext()) { dropped++; }
    while (iter.MoveNext()) { yield return iter.Current; }
}

public static IEnumerable Concat(object head, IEnumerable list)
{
    yield return head;
    foreach (var x in list) { yield return x; }
}

public static IEnumerable<IEnumerable> CrossProduct(IEnumerable<IEnumerable> lists)
{
    if (lists == null || lists.FirstOrDefault() == null) { yield break; }
    var heads = lists.First();
    var tails = CrossProduct(Drop(lists, 1));
    if (tails.FirstOrDefault() == null)
    {
    foreach (var h in heads) { yield return new object[] { h }; }
    }
    else
    {
    foreach (var head in heads)
    {
        foreach (var tail in tails)
        {
        yield return Concat(head, tail);
        }
    }
    }
}