Looking for a method that will print all combinations of an array of arrays.
Data type would look something like this:
// print all combos
var data [][]string
Example
Input: [[Lorem, Ipsum], [Alpha, Beta, Theta]]
Expected Output: Lorem Alpha, Lorem Beta, Lorem Theta, Ipsum Alpha, Ipsum Beta, Ipsum Theta
The arrays can be of arbitrary length. What's the best way to accomplish this?
I'd iterate the vector of indexes of the slices.
Single index iterator:
// Iterator of a slice index. `len` equals to the length of the slice
type IdxIter struct {
idx uint
len uint
}
// Returns true is the iteration is over.
func (i IdxIter) Done() bool {
return i.idx >= i.len
}
// Builds the next iteration value. If called for the last index,
// the next value's `Done` returns `true`.
func (i *IdxIter) Next() {
i.idx++
}
// Resets the iterator
func (i *IdxIter) Reset() {
i.idx = 0
}
// The index value
func (i IdxIter) Idx() uint {
return i.idx
}
Iterator of a vector of indexes:
// Index iterator for a slice of slices
type IdxVectorIter []IdxIter
// Returns true is the iteration is over.
func (ii IdxVectorIter) Done() bool {
last := len(ii) - 1
return ii[last].Done()
}
// Builds the next iteration value. If called for the last index vector,
// the next value's `Done` returns `true`.
func (ii IdxVectorIter) Next() {
if len(ii) == 0 {
return
}
last := len(ii) - 1
for pos := range ii[:last] {
ii[pos].Next()
if ii[pos].Done() {
ii[pos].Reset()
} else {
return
}
}
ii[last].Next()
}
With that the iteration over the slice of slices is simple:
func main() {
words := [][]string{
{"lorem", "ipsum"},
{},
{"Alpha", "Beta", "Gamma"},
{"X", "Y", "Z"},
}
// Fixed buffer for the combinations of words
dst := make([]string, len(words))
// Iteration loop
for ii := NewIdxVectorFromSlices(words); !ii.Done(); ii.Next() {
GetTo(words, dst, ii)
fmt.Printf("%v\n", dst)
}
}
Full code https://go.dev/play/p/ecjjcAEexZO
Output
[lorem Alpha X]
[ipsum Alpha X]
[lorem Beta X]
[ipsum Beta X]
[lorem Gamma X]
[ipsum Gamma X]
[lorem Alpha Y]
[ipsum Alpha Y]
[lorem Beta Y]
[ipsum Beta Y]
[lorem Gamma Y]
[ipsum Gamma Y]
[lorem Alpha Z]
[ipsum Alpha Z]
[lorem Beta Z]
[ipsum Beta Z]
[lorem Gamma Z]
[ipsum Gamma Z]