Combination of List<List<int>>
It's quite similar to this answer I gave to another question:
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();
For a variable number of inputs, now with added 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();
}
If the number of dimensions is fixed, this is simply SelectMany
:
var qry = from a in A
from b in B
from c in C
select new {A=a,B=b,C=c};
However, if the number of dimensions is controlled by the data, you need to use 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));
}
}
}
How about following way of generating combinations using .Join method?
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);
}
This Method GenerateCombinations(..) does main work of generating combinations. This method is generic so could be used for generating combinations of any type.
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;
}
Display helper..
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();
}