Combination of List<List<int>>
我有一个包含这个的列表
1 2 3 4 |
我想要像这样的所有组合
1 2 3 4 5 | 1-0-6 1-1-6 2-0-6 2-1-6 3-0-6 |
号
等等。
根据你的说法,使用LINQ是否可以解决这个问题?
这与我回答的另一个问题非常相似:
1 2 3 4 5 6 7 | 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(); |
对于数量可变的输入,现在添加了泛型:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | 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(); } |
。
如果尺寸的数量是固定的,这只是
1 2 3 4 |
但是,如果维度的数量由数据控制,则需要使用递归:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | 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方法生成组合的方法如何?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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); } |
这种方法生成组合(..)主要是生成组合。此方法是通用的,因此可以用于生成任何类型的组合。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | 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; } |
。
显示助手..
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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(); } |
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | //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 ",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[i].elements[temp[i]]); printf(" "); } } |
来自Abhijeet Nagre的伟大解决方案。当某些序列为空或序列为空时,改进幅度较小。
1 2 3 4 5 6 7 |
。
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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; } |
只是为了好玩:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | 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; } }"; } } } |
。