Создайте все комбинации значений n * m
Скажем, у меня есть структура данных 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 } }
который содержит каждую комбинацию значений из исходной структуры. Таким образом, каждый элемент в каждом внутреннем массиве сопоставляет по индексу элемент/массив в исходном внешнем массиве.
Каков самый простой способ сделать это на С#?
Ответы
Ответ 1
Вы можете использовать метод CartesianProduct
для Эрика Липперта для этого (взято из здесь):
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}));
}
Ответ 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)));
}