If you need to flatten ordered enumerables, that is taking one element of each enumerable, in order, to flatten a combination, here is a quick solution in C# and VB.NET, accompanied with an example:
Code in VB.NET:
Private Shared Sub GetCombinationsRec(Of T)(sources As IList(Of IEnumerable(Of T)), chain As T(), index As Integer, combinations As ICollection(Of T()))
For Each element As var In sources(index)
chain(index) = element
If index Is sources.Count - 1 Then
Dim finalChain = New T(chain.Length - 1) {}
chain.CopyTo(finalChain, 0)
combinations.Add(finalChain)
Else
GetCombinationsRec(sources := sources, chain := chain, index := index + 1, combinations := combinations)
End If
Next
End Sub
Public Shared Function GetCombinations(Of T)(ParamArray enumerables As IEnumerable(Of T)()) As List(Of T())
Dim combinations = New List(Of T())(enumerables.Length)
If enumerables.Length > 0 Then
Dim chain = New T(enumerables.Length - 1) {}
GetCombinationsRec(sources := enumerables, chain := chain, index := 0, combinations := combinations)
End If
Return combinations
End Function
Code in C#.NET:
private static void GetCombinationsRec<T>(IList<IEnumerable<T>> sources, T[] chain, int index, ICollection<T[]> combinations) {
foreach (var element in sources[index]) {
chain[index] = element;
if (index == sources.Count - 1) {
var finalChain = new T[chain.Length];
chain.CopyTo(finalChain, 0);
combinations.Add(finalChain);
}
else {
GetCombinationsRec(sources: sources, chain: chain, index: index + 1, combinations: combinations);
}
}
}
public static List<T[]> GetCombinations<T>(params IEnumerable<T>[] enumerables) {
var combinations = new List<T[]>(enumerables.Length);
if (enumerables.Length > 0) {
var chain = new T[enumerables.Length];
GetCombinationsRec(sources: enumerables, chain: chain, index: 0, combinations: combinations);
}
return combinations;
}
Usage is simple:
Dim list1 = New String() {"hello", "bonjour", "hallo", "hola"}
Dim list2 = New String() {"Erwin", "Larry", "Bill", "Steve"}
Dim list3 = New String() {"!", ".."}
Dim result = Utils.GetCombinations(list1, list2, list3)
For Each r In result
Debug.Print(String.Join(" "c, r))
Next
or in C#:
var list1 = new[] { "Hello", "Bonjour", "Hallo", "Hola" };
var list2 = new[] { "Erwin", "Larry", "Bill", "Steve" };
var list3 = new[] { "!", "..." };
var result = Utils.GetCombinations(list1, list2, list3);
foreach (r in result) {
Debug.Print(string.Join(" ", r));
}
As with any recursive function, memory usage can be exponential so make sure you know the number of target combinations is reasonable. Speed-wise, parallelizing this function is not worth it as we are just iterating over the elements.
Comments
Live comments coming soon. Until then, reach out via the contact page.
Historical comments (2, 2008–2025) — archived
I was unable to get the vb code to wrk
something about
Dim result = Utils.GetCombinations(list1, list2, list3)
It would error out here telling me to generate a stub please help
You have to declare the function as part of a public class named MyLib:
Public Class Utils
Public Shared Function GetCombinations(…)
End Function
End Class