Reputation: 5
I have several arrays in VB.net. These arrays have different lengths and I need the combination between them. The simple solution is using nested loop as in the example:
Dim Array1= {10, 11, 12}
Dim Array2= {15}
Dim Array3= {1,2,3}
Dim array(2) As Object
array(0) = Array1
array(1) = Array2
array(2) = Array3
for (a = 1 to < Array1.Length - 1)
for (b = 1 to < Array2.Length - 1)
for (c = 1 to < Array3.Length - 1)
'Get combination
Next
Next
Next
Output: {10,15,1},{10,15,2},{10,15,3},{11,15,1},{11,15,2},...
But the real problem is that the number of arrays is not a fixed parameter (could be 3 as in the example or any other number) and therefore nested loops is not a solution.
Any idea?
Upvotes: 0
Views: 814
Reputation: 39152
Here's a quick rewrite of some code I wrote almost a decade ago while still using VB.Net 2003...what great memories lying around in my hard drive!
Hope you find its output useful:
10,15,1
10,15,2
10,15,3
11,15,1
11,15,2
11,15,3
12,15,1
12,15,2
12,15,3
The code that generated it:
Public Class Form1
Private WithEvents FC As ArrayCombinations = Nothing
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
If IsNothing(FC) Then
FC = New ArrayCombinations
FC.AddArray(New Integer() {10, 11, 12})
FC.AddArray(New Integer() {15})
FC.AddArray(New Integer() {1, 2, 3})
FC.GenerateCombos()
End If
End Sub
Private Sub FC_combinations(combos As System.Collections.Generic.List(Of System.Collections.Generic.List(Of Integer))) Handles FC.Combinations
For Each combo As List(Of Integer) In combos
Debug.Print(String.Join(",", combo.Select(Function(i) i.ToString())))
Next
FC = Nothing
End Sub
End Class
Public Class ArrayCombinations
Private Arrays As New List(Of Integer())
Private WithEvents BGW As New System.ComponentModel.BackgroundWorker
Public Event Combinations(ByVal combos As List(Of List(Of Integer)))
Public Sub New()
BGW.WorkerReportsProgress = True
End Sub
Public Sub AddArray(ByVal values() As Integer)
If Not BGW.IsBusy Then
Arrays.Add(values)
End If
End Sub
Public Sub GenerateCombos()
If Not BGW.IsBusy Then
BGW.RunWorkerAsync()
End If
End Sub
Private Sub BGW_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BGW.DoWork
Dim sizes As New List(Of Integer)
Dim combinations As Integer
Dim remainder As Integer
Dim quotient As Integer
Dim combination As List(Of Integer)
Dim combos As New List(Of List(Of Integer))
If Arrays.Count > 0 Then
combinations = 1
For Each factor() As Integer In Arrays
sizes.Add(factor.Count)
combinations = combinations * factor.Count
Next
For i As Integer = 0 To combinations - 1
combination = New List(Of Integer)
For j As Integer = 1 To Arrays.Count
combination.Add(Nothing)
Next
quotient = i \ sizes.Item(sizes.Count - 1) ' Integer Division
remainder = i Mod sizes.Item(sizes.Count - 1)
combination(Arrays.Count - 1) = Arrays.Item(Arrays.Count - 1)(remainder)
For j As Integer = (sizes.Count - 2) To 0 Step -1
combination.Item(j) = Arrays.Item(j)(quotient Mod sizes.Item(j))
quotient = quotient \ sizes.Item(j) ' Integer Division
Next
combos.Add(combination)
Next
e.Result = combos
End If
End Sub
Private Sub BGW_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BGW.RunWorkerCompleted
RaiseEvent Combinations(e.Result)
End Sub
End Class
Upvotes: 1
Reputation: 34834
You can create a list to hold the combined values from all the arrays and then push those values back into an array, like this:
Dim listCombined = New List(Of Integer)
listCombined.AddRange(array1)
listCombined.AddRange(array2)
listCombined.AddRange(array3)
Dim arrayCombined As Integer() = listCombined.ToArray()
Note: This example assumes you have integer arrays, but you can change the type to whatever the arrays actually hold. You can also loop through the arrays instead of listing them one by one for the AddRange
calls.
Upvotes: 0