Вот нерекурсивное решение, которое может обрабатывать любое количество наборов, где каждый набор имеет переменное количество элементов:
Sub Main()
Dim input As New List(Of List(Of String)) From {
New List(Of String) From {"a", "b", "c"},
New List(Of String) From {"d", "e"},
New List(Of String) From {"f", "g", "h", "i"}
}
For Each combination In CartesianProducts(input)
Console.WriteLine(String.Join(",", combination))
Next
Console.Write("Press Enter to quit...")
Console.ReadLine()
End Sub
Public Iterator Function CartesianProducts(ByVal setList As List(Of List(Of String))) As IEnumerable(Of IEnumerable(Of String))
Dim curIndex(setList.Count - 1) As Integer ' tells which item is currently being used from each set
Dim setSizes = setList.Select(Function(curSet) curSet.Count) ' tells the number of items in each set
Dim numCombinations As Integer = setSizes.Aggregate(Function(a, b) a * b) ' alls the sizes multiplied together
For i As Integer = 1 To numCombinations
' return the current combination by gathering all the elements from each set using "curIndex"
Yield Enumerable.Range(0, curIndex.Count).Select(Function(x) setList(x)(curIndex(x)))
' working backwards, increment the index in each slot
' if the new number equals the set size, reset to zero ...
' ...and let the loop continue, which will increment the index to the left
' if the new number was less than size for that set, simply exit the loop as you're done
For j As Integer = curIndex.Count - 1 To 0 Step -1
curIndex(j) = curIndex(j) + 1
If curIndex(j) = setSizes(j) Then
curIndex(j) = 0
Else
Exit For
End If
Next
Next
End Function
Вывод:
a,d,f
a,d,g
a,d,h
a,d,i
a,e,f
a,e,g
a,e,h
a,e,i
b,d,f
b,d,g
b,d,h
b,d,i
b,e,f
b,e,g
b,e,h
b,e,i
c,d,f
c,d,g
c,d,h
c,d,i
c,e,f
c,e,g
c,e,h
c,e,i
Press Enter to quit...
Вот визуальный представление того, что делает массив curIndex
:
[ 0,0,0 ]
[ 0,0,1 ]
[ 0,0,2 ]
[ 0,0,3 ]
[ 0,1,0 ]
[ 0,1,1 ]
[ 0,1,2 ]
[ 0,1,3 ]
[ 1,0,0 ]
[ 1,0,1 ]
[ 1,0,2 ]
[ 1,0,3 ]
[ 1,1,0 ]
[ 1,1,1 ]
[ 1,1,2 ]
[ 1,1,3 ]
[ 2,0,0 ]
[ 2,0,1 ]
[ 2,0,2 ]
[ 2,0,3 ]
[ 2,1,0 ]
[ 2,1,1 ]
[ 2,1,2 ]
[ 2,1,3 ]