Подтвердить что ты не робот

Создайте все комбинации значений 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 } }

который содержит каждую комбинацию значений из исходной структуры. Таким образом, каждый элемент в каждом внутреннем массиве сопоставляет по индексу элемент/массив в исходном внешнем массиве.

Каков самый простой способ сделать это на С#?

4b9b3361

Ответ 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)));
    }