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?
CodePudding user response:
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]