Combinação de List <List >

Eu tenho uma lista deste tipo Lista> que contém este

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

Eu quero ter todas as combinações como esta

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

e assim por diante.

De acordo com você é possível resolver usando o Linq?

É bem parecido com essa resposta que dei a outra pergunta:

 var combinations = from a in A from b in B from c in C orderby a, b, c select new List { a, b, c }; var x = combinations.ToList(); 

Para um número variável de inputs, agora com os genéricos adicionados:

 var x = AllCombinationsOf(A, B, C); public static List> AllCombinationsOf(params List[] sets) { // need array bounds checking etc for production var combinations = new List>(); // prime the data foreach (var value in sets[0]) combinations.Add(new List { value }); foreach (var set in sets.Skip(1)) combinations = AddExtraSet(combinations, set); return combinations; } private static List> AddExtraSet (List> combinations, List set) { var newCombinations = from value in set from combination in combinations select new List(combination) { value }; return newCombinations.ToList(); } 

Se o número de dimensões for fixo, isso é simplesmente SelectMany :

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

No entanto, se o número de dimensões for controlado pelos dados, você precisará usar recursion:

 static void Main() { List> outerList = new List> { new List(){1, 2, 3, 4, 5}, new List(){0, 1}, new List(){6,3}, new List(){1,3,5} }; int[] result = new int[outerList.Count]; Recurse(result, 0, outerList); } static void Recurse(int[] selected, int index, IEnumerable remaining) where TList : IEnumerable { IEnumerable 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)); } } } 

Que tal seguir a maneira de gerar combinações usando o método .Join?

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

Este método GenerateCombinations (..) faz o trabalho principal de gerar combinações. Esse método é genérico, portanto, pode ser usado para gerar combinações de qualquer tipo.

 private static List> GenerateCombinations( List> collectionOfSeries) { List> generatedCombinations = collectionOfSeries.Take(1) .FirstOrDefault() .Select(i => (new T[]{i}).ToList()) .ToList(); foreach (List series in collectionOfSeries.Skip(1)) { generatedCombinations = generatedCombinations .Join(series as List, combination => true, i => true, (combination, i) => { List nextLevelCombination = new List(combination); nextLevelCombination.Add(i); return nextLevelCombination; }).ToList(); } return generatedCombinations; } 

Mostrar ajudante ..

 private static void Display(List> 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(); } 
 //Done in 2 while loops. No recursion required #include #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 

Apenas por diversão:

 using CSScriptLibrary; using System; using System.Collections.Generic; namespace LinqStringTest { public class Program { static void Main(string[] args) { var lists = new List>() { new List { 0, 1, 2, 3 }, new List { 4, 5 }, new List { 6, 7 }, new List { 10,11,12 }, }; var code = GetCode(lists); AsmHelper scriptAsm = new AsmHelper(CSScript.LoadCode(code)); var result = (IEnumerable)scriptAsm.Invoke("Script.LinqCombine", lists); foreach (var item in result) { Console.WriteLine(item); } Console.ReadLine(); } private static string GetCode(List> 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 LinqCombine(List> lists) { var x = " + froms + @" select new { " + selects + @" }; return x; } }"; } } } 
  public static List> CrossProduct(List> s) { if (!s.Any()) return new List>(); 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; } 

Ótima solução de Abhijeet Nagre. Pequena melhoria no caso de alguma série estar vazia ou a série estar vazia.

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