Recursive algorithm to generate all combinations of elements in arrays

If you have a list of lists of objects implementing IEnumerable (such as Arrays or Lists), it may occasionally be useful to flatten them to generate all possible combinations. Here is my quick solution in VB and C#.NET (you may of course use the underlying pseudocode to translate it into other languages), with an overload to facilitate the function call, and an example:

Code in VB.NET:

Public Shared Function GetCombinationsFromIEnumerables(ByRef chain() As Object, ByRef IEnumerables As IEnumerable(Of IEnumerable(Of Object))) As List(Of Object())
    Dim Combinations As New List(Of Object())
    If IEnumerables.Any Then
        For Each v In IEnumerables.First
            Combinations.AddRange(GetCombinationsFromIEnumerables(chain.Concat(New Object() {v}).ToArray, IEnumerables.Skip(1)).ToArray)
        Next
    Else
        Combinations.Add(chain)
    End If
    Return Combinations
End Function

Public Shared Function GetCombinationsFromIEnumerables(ByVal ParamArray IEnumerables() As IEnumerable(Of Object)) As List(Of Object())
    Return GetCombinationsFromIEnumerables(chain:=New Object() {}, IEnumerables:=IEnumerables.AsEnumerable)
End Function

Code in C#.NET:

public static List<object[]> GetCombinationsFromIEnumerables(ref object[] chain, ref IEnumerable<IEnumerable<object>> IEnumerables)
{
List<object[]> Combinations = new List<object[]>();
if (IEnumerables.Any) {
    foreach ( v in IEnumerables.First) {
        Combinations.AddRange(GetCombinationsFromIEnumerables(chain.Concat(new object[] { v }).ToArray, IEnumerables.Skip(1)).ToArray);
    }
} else {
    Combinations.Add(chain);
}
return Combinations;
}

public static List<object[]> GetCombinationsFromIEnumerables(params IEnumerable<object>[] IEnumerables)
{
return GetCombinationsFromIEnumerables(chain = new object[], IEnumerables = IEnumerables.AsEnumerable);
}

Usage is simple:

Dim list1 = New String() {"hello", "bonjour", "hallo", "hola"}
Dim list2 = New String() {"Erwin", "Larry", "Bill"}
Dim list3 = New String() {"!", ".."}
Dim result = MyLib.GetCombinationsFromIEnumerables(list1, list2, list3)
For Each r In result
    Debug.Print(String.Join(" "c, r))
Next

or in C#:

object list1 = new string[] {"hello","bonjour","hallo","hola"};
object list2 = new string[] {"Erwin", "Larry", "Bill"};
object list3 = new string[] {"!",".."};
object result = MyLib.GetCombinationsFromIEnumerables(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 how much data is going to be processed.

To parallelize this function, we would have to embed the content of the for each loop into a lambda function using:

IEnumerables.First.AsParallel().AsOrdered().ForEach

if order is important, otherwise simply:

IEnumerables.First.AsParallel().ForAll

However, unless there is a fair amount of processing involved (which apparently is not the case here as we are just iterating over elements), it is not worth parallelizing.