List <List <int >>的组合
我有这种types列表>包含这个
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?
这与我给另一个问题的回答非常相似:
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();
对于可变数量的input,现在添加了generics:
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(); }
如果维数是固定的,这只是SelectMany
:
var qry = from a in A from b in B from c in C select new {A=a,B=b,C=c};
但是,如果维数由数据控制,则需要使用recursion:
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)); } } }
如何使用.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(..)做生成组合的主要工作。 此方法是通用的,因此可用于生成任何types的组合。
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(); }
//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"); } }
只是为了好玩:
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; } }"; } } }
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; }