Arrays LINQ中n个集合的置换生成
我有一个IEnumerable(IEnumerable[])数组,并希望生成这些IEnumerable中所有可能的元素组合。 与此问题类似: 但是我不知道我之前会有多少IEnumerables,因此无法使用所描述的LINQ语句 举个例子: 我的阵列 例如,有这些元素Arrays LINQ中n个集合的置换生成,arrays,linq,ienumerable,permutation,combinations,Arrays,Linq,Ienumerable,Permutation,Combinations,我有一个IEnumerable(IEnumerable[])数组,并希望生成这些IEnumerable中所有可能的元素组合。 与此问题类似: 但是我不知道我之前会有多少IEnumerables,因此无法使用所描述的LINQ语句 举个例子: 我的阵列 例如,有这些元素 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}; arra
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};
然后我需要适当的排列。我没有关于有多少IEnumerable的任何信息,也没有关于每个IEnumerable包含多少元素的信息
提前感谢您的帮助
Lars尝试将此作为一个方向(我确信您需要修改,而且我还没有编译它,因此可能存在一些语法错误)
public IEnumerable编译名
(IEnumberable数组、列表组合)
{
如果(combinations==null)combinations=new List();
对于(int i=arrays.Count()-1;i>=0;i--)
{
如果(combinations.Count>=1)组合=
组合2列表(组合、数组[i]);
其他的
{
组合=组合2列表(数组[i],数组[i-1];
我--;
}
}
收益组合;
}
私有列表组合列表
(IEnumerable列表1、IEnumerable列表2)
{
List currentList=新列表();
对于(int i=0;i
同样,没有编译,但它应该做的是继续将“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]添加到第一个to之后将产生:{a,1,x},{a,1,y},{a,1,z}
等等。似乎您想要笛卡尔乘积。这应该可以,尽管我没有特别仔细地研究边缘情况
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);
}
}
}
}
公共静态IEnumerable Drop(IEnumerable列表,长numToDrop)
{
if(numToDrop<0){throw new ArgumentException(“要删除的数字必须是非负的”);}
长期下降=0;
var iter=list.GetEnumerator();
而(drop
当您的输入是数组[0]={0,1,2};数组[1]={a,b};数组[2]={w,x,y,z}时,您希望输出是什么?如上所述,我不知道预期的输出真的算作所有的排列。你是否有一个假设的约束,即每个结果项只有两个元素?也可能是引用的重复:@David V:我的预期输出将是{0,a,w},{0,a,x},{0,a,y},{0,a,z},{0,b,x},{0,b,y},{0,b,z},{1,a,w}@Anthony Pegram:Eric Lippert的文章是我一直在寻找的,非常好而且干净。我只是还有一个问题。因为我说过我需要代码来处理一系列非类型的IEnumerable(IEnumerable[])我正在努力让Erics代码正常工作。使用类型化IEnumerables是完美的。尽管如上所述,Eric Lippert在Anthony linked问题上的解决方案要漂亮得多。谢谢Rob,这很有效!Eric的解决方案非常优雅,我同意,但因为我使用的是非类型化集合,所以我不能使用它(或不知道如何使用)。我的集合中的元素可以是从int到object的任何元素,尽管每个集合本身都是一致的。谢谢。我没有尝试过上面的代码,因为它对字符串进行操作,Rob的代码正是我所需要的,但仔细看,我想我可以很容易地修改它。
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;
}
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);
}
}
}
}