Комбинация списка <Список <int>>

У меня есть список этого типа List > , который содержит этот

List<int> A = new List<int> {1, 2, 3, 4, 5};
List<int> B = new List<int> {0, 1};
List<int> C = new List<int> {6};
List<int> X = new List<int> {....,....};

Я хочу иметь все комбинации вроде этого

1-0-6
1-1-6
2-0-6
2-1-6
3-0-6

и т.д.

По вашему мнению, это можно решить с помощью Linq?

Ответ 1

Это очень похоже на этот ответ Я дал еще один вопрос:

var combinations = from a in A
                   from b in B
                   from c in C
                   orderby a, b, c
                   select new List<int> { a, b, c };

var x = combinations.ToList();

Для переменного количества входов, теперь с добавленными дженериками:

var x = AllCombinationsOf(A, B, C);

public static List<List<T>> AllCombinationsOf<T>(params List<T>[] sets)
{
    // need array bounds checking etc for production
    var combinations = new List<List<T>>();

    // prime the data
    foreach (var value in sets[0])
        combinations.Add(new List<T> { value });

    foreach (var set in sets.Skip(1))
        combinations = AddExtraSet(combinations, set);

    return combinations;
}

private static List<List<T>> AddExtraSet<T>
     (List<List<T>> combinations, List<T> set)
{
    var newCombinations = from value in set
                          from combination in combinations
                          select new List<T>(combination) { value };

    return newCombinations.ToList();
}

Ответ 2

Если число измерений фиксировано, это просто SelectMany:

var qry = from a in A
          from b in B
          from c in C
          select new {A=a,B=b,C=c};

Однако, если количество измерений контролируется данными, вам необходимо использовать рекурсию:

static void Main() {
    List<List<int>> outerList = new List<List<int>>
    {   new List<int>(){1, 2, 3, 4, 5},
        new List<int>(){0, 1},
        new List<int>(){6,3},
        new List<int>(){1,3,5}
    };
    int[] result = new int[outerList.Count];
    Recurse(result, 0, outerList);
}
static void Recurse<TList>(int[] selected, int index,
    IEnumerable<TList> remaining) where TList : IEnumerable<int> {
    IEnumerable<int> nextList = remaining.FirstOrDefault();
    if (nextList == null) {
        StringBuilder sb = new StringBuilder();
        foreach (int i in selected) {
            sb.Append(i).Append(',');
        }
        if (sb.Length > 0) sb.Length--;
        Console.WriteLine(sb);
    } else {
        foreach (int i in nextList) {
            selected[index] = i;
            Recurse(selected, index + 1, remaining.Skip(1));
        }
    }
}

Ответ 3

Как насчет следующего способа генерации комбинаций с использованием метода .Join?

static void Main()
{
    List<List<int>> collectionOfSeries = new List<List<int>>
                                {   new List<int>(){1, 2, 3, 4, 5},
                                    new List<int>(){0, 1},
                                    new List<int>(){6,3},
                                    new List<int>(){1,3,5}
                                };
    int[] result = new int[collectionOfSeries.Count];

    List<List<int>> combinations = GenerateCombinations(collectionOfSeries);

    Display(combinations); 
}

Этот метод GenerateCombinations (..) выполняет основную работу по созданию комбинаций. Этот метод является общим, поэтому его можно использовать для генерации комбинаций любого типа.

private static List<List<T>> GenerateCombinations<T>(
                                List<List<T>> collectionOfSeries)
{
    List<List<T>> generatedCombinations = 
        collectionOfSeries.Take(1)
                          .FirstOrDefault()
                          .Select(i => (new T[]{i}).ToList())                          
                          .ToList();

    foreach (List<T> series in collectionOfSeries.Skip(1))
    {
        generatedCombinations = 
            generatedCombinations
                  .Join(series as List<T>,
                        combination => true,
                        i => true,
                        (combination, i) =>
                            {
                                List<T> nextLevelCombination = 
                                    new List<T>(combination);
                                nextLevelCombination.Add(i);
                                return nextLevelCombination;
                            }).ToList();

    }

    return generatedCombinations;
}

Вспомогательный дисплей.

private static void Display<T>(List<List<T>> generatedCombinations)
{
    int index = 0;
    foreach (var generatedCombination in generatedCombinations)
    {
        Console.Write("{0}\t:", ++index);
        foreach (var i in generatedCombination)
        {
            Console.Write("{0,3}", i);
        }
        Console.WriteLine();
    }
    Console.ReadKey();
}

Ответ 4

//Done in 2 while loops. No recursion required
#include<stdio.h>
#define MAX 100
typedef struct list
{
  int elements[MAX];
}list;
list n[10];
int number,count[10],temp[10];
void print();
int main()
{
  int i,j,mult=1,mult_count;
  printf("Enter the number of lists - ");
  scanf("%d",&number);
  for(i=0;i<number;i++)
  {
    printf("Enter the number of elements - ");
    scanf("%d",&count[i]);
    for(j=0;i<count[i];j++)
    {
      printf("Enter element %d - "j);
      scanf("%d",&n[i].elements[j]);
    }
  }
  for(i=0;i<number;i++)
  temp[i]=0;
  for(i=0;i<number;i++)
  mult*=count[i];
  printf("%d\n",mult);
  mult_count=0;
  while(1)
  {
    print();
    mult_count++;
    if(mult_count==mult)
    break;
    i=0;
    while(1)
    {
      temp[i]++;
      if(temp[i]==count[i])
      {
        temp[i]=0;
        i++;
      }
      else break;
    }
  }
  return 0;
}
void print()
{
  int i;
  for(i=0;i<number;i++)
  {
    printf("%d\n",n[i].elements[temp[i]]);
    printf("\n");
  }
}

Ответ 5

    public static List<List<string>> CrossProduct(List<List<string>> s)
    {
        if (!s.Any())
            return new List<List<string>>();

        var c1 = s.First();
        var cRest = s.Skip(1).ToList();
        var sss = from v1 in c1
                  from vRest in CrossProduct(cRest)
                  select (new[] { v1 }.Concat(vRest)).ToList();
        var r = sss.ToList();
        return r;
    }

Ответ 6

Просто для удовольствия:

using CSScriptLibrary;
using System;
using System.Collections.Generic;

namespace LinqStringTest
{
    public class Program
    {
        static void Main(string[] args)
        {

            var lists = new List<List<int>>() {
                new List<int> { 0, 1, 2, 3 },
                new List<int> { 4, 5 },
                new List<int> { 6, 7 },
                new List<int> { 10,11,12 },
            };
            var code = GetCode(lists);
            AsmHelper scriptAsm = new AsmHelper(CSScript.LoadCode(code));

            var result = (IEnumerable<dynamic>)scriptAsm.Invoke("Script.LinqCombine", lists);

            foreach (var item in result)
            {
                Console.WriteLine(item);
            }

            Console.ReadLine();
        }

        private static string GetCode(List<List<int>> listsToCombine)
        {
            var froms = "";
            var selects = "";

            for (int i = 0; i < listsToCombine.Count; i++)
            {
                froms += string.Format("from d{0} in lists[{0}]{1}", i, Environment.NewLine);
                selects += string.Format("D{0} = d{0},", i);
            }

            return @"using System;
              using System.Linq;
              using System.Collections.Generic;
              public class Script
              {
                  public static IEnumerable<dynamic> LinqCombine(List<List<int>> lists)
                  {
                        var x = " + froms + @"
                                select new { " + selects + @" };
                        return x;
                  }
              }";
        }
    }
}

Ответ 7

Отличное решение от Abhijeet Nagre. Небольшое улучшение в случае, если какая-либо серия пуста или серия пуста.

List<List<T>> generatedCombinations = 
    collectionOfSeries.Where(l => l.Any())
                      .Take(1)
                      .DefaultIfEmpty(new List<T>())
                      .First()
                      .Select(i => (new T[]{i}).ToList())                          
                      .ToList();