我有一系列名单
List<string>[] possibleLines;
每个List&lt;&gt;的数组也可以具有不同的大小。可以有不同数量的字符串。前例
List<string>[0]
- 可以有字符串“first string”,“second string”List<string>[1]
- “第三个字符串”,“第四个字符串”,“第五个字符串”我需要获得所有可能的组合,每个字符串必须来自不同的列表(数组大小可能不同)。例如
等等。
答案 0 :(得分:5)
你在这里做的是计算未知数量的集合的笛卡尔积。 Eric Lippert描述了如何在this blog post中编写这个问题的解决方案(我强烈建议你阅读以了解他是如何提出这个解决方案的。)
他最终得到的代码是:
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 :(得分:1)
我认为这是一个非常酷的数学问题,但我想想象实际的过程,所以我写了这个想要测试Servy(好吧,Eric Lippert)写的:
int length = 4;
var lists = new List<List<string>>();
var random = new Random(1234);
for(int i = 0; i < length; i++)
{
var inLength = random.Next(4, 8);
var tempList = new List<string();
for (int j = 0; j < inLength; j++_
{
tempList.Add(string.Format("{{String Coords: {0}, {1}}}", i, j));
}
lists.Add(tempList);
}
var cp= lists.CartesianProduct();
var output = RenderString(cp);
和RenderString
:
private static string RenderString(IEnumerable<IEnumerable<string>> cp)
{
var sb = new StringBuilder();
foreach (var item in cp)
{
sb.AppendLine(item.Aggregate((a, b) => a + b));
}
return sb.ToString();
}
这会给你一个output
看起来像
{String Coords: 0, 0}{String Coords: 1, 0}{String Coords: 2, 0}{String Coords: 3, 0}
{String Coords: 0, 0}{String Coords: 1, 0}{String Coords: 2, 0}{String Coords: 3, 1}
{String Coords: 0, 0}{String Coords: 1, 0}{String Coords: 2, 0}{String Coords: 3, 2}
{String Coords: 0, 0}{String Coords: 1, 0}{String Coords: 2, 0}{String Coords: 3, 3}
{String Coords: 0, 0}{String Coords: 1, 0}{String Coords: 2, 0}{String Coords: 3, 4}
{String Coords: 0, 0}{String Coords: 1, 0}{String Coords: 2, 1}{String Coords: 3, 0}
...
{String Coords: 0, 4}{String Coords: 1, 4}{String Coords: 2, 6}{String Coords: 3, 4}
如果您想要了解正在发生的事情,那就太酷了。
答案 2 :(得分:0)
这是一种程序性更强的方法,读起来很恐怖,但速度是埃里克·利珀特(Eric Lippert)建议的两倍。
static IReadOnlyList<IReadOnlyList<T>> CartesianProduct<T>(this IEnumerable<IEnumerable<T>> sequences)
{
var arrays = sequences.Select(s => s.ToArray()).ToArray();
var numColumns = arrays.Length;
if (numColumns == 0)
{
return new[]
{
Array.Empty<T>()
};
}
var arrayLengths = arrays.Select(l => l.Length).ToArray();
var arrayIndices = new int[numColumns];
var numRows = arrayLengths.Aggregate((x, y) => x * y);
var lastColumnIndex = numColumns - 1;
var combinations = new IReadOnlyList<T>[numRows];
for (var rowIndex = 0; rowIndex < numRows; rowIndex++)
{
var items = new T[numColumns];
for (var columnIndex = 0; columnIndex < numColumns; columnIndex++)
{
items[columnIndex] = arrays[columnIndex][arrayIndices[columnIndex]];
}
combinations[rowIndex] = items;
for (var i = lastColumnIndex; i >= 0; i--)
{
var updatedIndex = arrayIndices[i] = (arrayIndices[i] + 1) % arrayLengths[i];
if (updatedIndex > 0)
{
break;
}
}
}
return combinations;
}