It looks like you need this feature from the Eric Lippert blog post written in response to Creating all possible combinations :
public static IEnumerable<IEnumerable<T>> CartesianProduct<T>( this IEnumerable<IEnumerable<T>> sequences) { IEnumerable<IEnumerable<T>> emptyProduct = new[] { Enumerable.Empty<T>() }; return sequences.Aggregate( emptyProduct, (accumulator, sequence) => from accseq in accumulator from item in sequence select accseq.Concat(new[] {item})); }
This will allow you to write code like this:
int[][] items = { new[] { 11001, 54010, 60621 }, new[] { 11001, 60621 }, new[] { 60621 } }; var routes = CartesianProduct(items); foreach (var route in routes) Console.WriteLine(string.Join(", ", route));
And we get the following conclusion:
11001, 11001, 60621
11001, 60621, 60621
54010, 11001, 60621
54010, 60621, 60621
60621, 11001, 60621
60621, 60621, 60621
EDIT: here is the version of VB.NET (in VS2010)
Imports System.Runtime.CompilerServices Module Module1 <Extension()> Private Function CartesianProduct(Of T)( ByVal sequences As IEnumerable(Of IEnumerable(Of T))) _ As IEnumerable(Of IEnumerable(Of T)) Dim emptyProduct As IEnumerable(Of IEnumerable(Of T)) = New IEnumerable(Of T)() {Enumerable.Empty(Of T)()} Return sequences.Aggregate( emptyProduct, Function(accumulator, sequence) Return (From accseq In accumulator From item In sequence Select accseq.Concat(New T() {item})) End Function) End Function Sub Main(ByVal args As String()) Dim items = New Integer()() {New Integer() {11001, 54010, 60621}, New Integer() {11001, 60621}, New Integer() {60621}} Dim routes = items.CartesianProduct() Dim route As IEnumerable(Of Integer) For Each route In routes Console.WriteLine(String.Join(", ", route)) Next End Sub End Module
Of course, if you do not need any LINQ, here is a complete recursive implementation without LINQ:
public static IEnumerable<IEnumerable<T>> CartesianProduct<T>( this IEnumerable<IEnumerable<T>> sequences) { var accum = new List<T[]>(); var list = sequences.ToList(); if (list.Count > 0) CartesianRecurse(accum, new Stack<T>(), list, list.Count - 1); return accum; } static void CartesianRecurse<T>(List<T[]> accum, Stack<T> stack, List<IEnumerable<T>> list, int index) { foreach (T item in list[index]) { stack.Push(item); if (index == 0) accum.Add(stack.ToArray()); else CartesianRecurse(accum, stack, list, index - 1); stack.Pop(); } }
It does not return elements in the same order as the first function, but is otherwise functionally identical. If you don't like LINQ or recursion, here's one LINQ-less method that does the same thing as the recursive version:
public static IEnumerable<IEnumerable<T>> CartesianProduct<T>( this IEnumerable<IEnumerable<T>> sequences) { var accum = new List<T[]>(); var list = sequences.ToList(); if (list.Count > 0) { var enumStack = new Stack<IEnumerator<T>>(); var itemStack = new Stack<T>(); int index = list.Count - 1; var enumerator = list[index].GetEnumerator(); while (true) if (enumerator.MoveNext()) { itemStack.Push(enumerator.Current); if (index == 0) { accum.Add(itemStack.ToArray()); itemStack.Pop(); } else { enumStack.Push(enumerator); enumerator = list[--index].GetEnumerator(); } } else { if (++index == list.Count) break; itemStack.Pop(); enumerator = enumStack.Pop(); } } return accum; }