我会迭代切片索引的向量。
单索引迭代器:
// 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
}
索引向量的迭代器:
// 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()
}
这样,切片切片的迭代就很简单了:
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)
}
}
完整代码https://go.dev/play/p/ecjjcAEexZO
输出
[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]