【问题标题】:How to create cartesian product [duplicate]如何创建笛卡尔积[重复]
【发布时间】:2014-06-18 04:39:12
【问题描述】:

我有一个整数列表,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 中执行此操作的惯用方法是什么?

初步猜测是一个返回整数切片的闭包,但感觉不是很干净。

【问题讨论】:

    标签: iterator go cartesian-product


    【解决方案1】:

    例如,

    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]
    

    【讨论】:

    【解决方案2】:

    按字典顺序查找下一个产品的代码很简单:从右侧开始,找到第一个在递增时不会翻转的值,递增该值并将右侧的值归零。

    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 个元素。

    【讨论】:

      【解决方案3】:

      只要关注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)
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2016-11-22
        • 2012-02-24
        • 2011-09-18
        • 2016-06-26
        • 1970-01-01
        • 2012-02-25
        • 2021-05-06
        • 2021-07-17
        • 1970-01-01
        相关资源
        最近更新 更多