我有一个整数列表a = [0, ..., n]
。我想从a生成k个元素的所有可能组合;即,a的笛卡尔积与其自身k次。请注意,n和k都可以在运行时更改,因此这至少需要一个可调整的函数。
所以如果n是3,k是2:
a = [0, 1, 2, 3]
k = 2
desired = [(0,0), (0, 1), (0, 2), ..., (2,3), (3,0), ..., (3,3)]
在python中我会使用itertools.product()函数:
for p in itertools.product(a, repeat=2):
print p
在Go 中执行此操作的惯用方法是什么?
初始猜测是一个闭包,它返回一个整数切片,但它感觉不是很干净。
答案 0 :(得分:5)
例如,
package main
import "fmt"
func nextProduct(a []int, r int) func() []int {
p := make([]int, r)
x := make([]int, len(p))
return func() []int {
p := p[:len(x)]
for i, xi := range x {
p[i] = a[xi]
}
for i := len(x) - 1; i >= 0; i-- {
x[i]++
if x[i] < len(a) {
break
}
x[i] = 0
if i <= 0 {
x = x[0:0]
break
}
}
return p
}
}
func main() {
a := []int{0, 1, 2, 3}
k := 2
np := nextProduct(a, k)
for {
product := np()
if len(product) == 0 {
break
}
fmt.Println(product)
}
}
输出:
[0 0]
[0 1]
[0 2]
[0 3]
[1 0]
[1 1]
[1 2]
[1 3]
[2 0]
[2 1]
[2 2]
[2 3]
[3 0]
[3 1]
[3 2]
[3 3]
答案 1 :(得分:1)
只需按照Implement Ruby style Cartesian product in Go的答案,在http://play.golang.org/p/NR1_3Fsq8F
上播放package main
import "fmt"
// NextIndex sets ix to the lexicographically next value,
// such that for each i>0, 0 <= ix[i] < lens.
func NextIndex(ix []int, lens int) {
for j := len(ix) - 1; j >= 0; j-- {
ix[j]++
if j == 0 || ix[j] < lens {
return
}
ix[j] = 0
}
}
func main() {
a := []int{0, 1, 2, 3}
k := 2
lens := len(a)
r := make([]int, k)
for ix := make([]int, k); ix[0] < lens; NextIndex(ix, lens) {
for i, j := range ix {
r[i] = a[j]
}
fmt.Println(r)
}
}
答案 2 :(得分:1)
以字典顺序查找下一个产品的代码很简单:从右边开始,找到第一个在递增时不会翻转的值,将其递增并将值归零到右边。
package main
import "fmt"
func main() {
n, k := 5, 2
ix := make([]int, k)
for {
fmt.Println(ix)
j := k - 1
for ; j >= 0 && ix[j] == n-1; j-- {
ix[j] = 0
}
if j < 0 {
return
}
ix[j]++
}
}
我已将“n”改为意味着该集合为[0,1,...,n-1],而不是问题中给出的[0,1,...,n],因为后者令人困惑,因为它有n + 1个元素。