英文:
Implement Ruby style Cartesian product in Go
问题
我想要获取a
、b
、c
、d
的笛卡尔积:
a = ['a1']
b = ['b1', 'b2']
c = ['c1', 'c2', 'c3']
d = ['d1']
以下是Ruby代码:
e = [b, c, d]
print a.product(*e)
输出结果为:
[
["a1", "b1", "c1", "d1"],
["a1", "b1", "c2", "d1"],
["a1", "b1", "c3", "d1"],
["a1", "b2", "c1", "d1"],
["a1", "b2", "c2", "d1"],
["a1", "b2", "c3", "d1"]
]
在Golang中是否有类似的包或函数可以实现笛卡尔积?这只是一个简化版本,实际上输入数据可能是这样的:[['a1'], ['b1','b2'], ['c1','c2','c3'],['d1'],['e1',...],...]。
英文:
I want to get the Cartesian product of a
, b
, c
, d
:
a = ['a1']
b = ['b1', 'b2']
c = ['c1', 'c2', 'c3']
d = ['d1']
Here is code in Ruby:
e = [b, c, d]
print a.product(*e)
Output is:
[
["a1", "b1", "c1", "d1"],
["a1", "b1", "c2", "d1"],
["a1", "b1", "c3", "d1"],
["a1", "b2", "c1", "d1"],
["a1", "b2", "c2", "d1"],
["a1", "b2", "c3", "d1"]
]
Is there a similar package or function that could do product in Golang?
This is just simplified version, in fact, the input data is like [['a1'], ['b1','b2'], ['c1','c2','c3],['d1'],['e1',...],...].
答案1
得分: 8
如果您需要在编译时未知的嵌套索引循环集,可以使用以下代码:
package main
import "fmt"
// NextIndex将ix设置为字典顺序的下一个值,
// 对于每个i>0,0 <= ix[i] < lens(i)。
func NextIndex(ix []int, lens func(i int) int) {
for j := len(ix) - 1; j >= 0; j-- {
ix[j]++
if j == 0 || ix[j] < lens(j) {
return
}
ix[j] = 0
}
}
func main() {
e := [][]string{
{"a1"},
{"b1", "b2"},
{"c1", "c2", "c3"},
{"d1"},
}
lens := func(i int) int { return len(e[i]) }
for ix := make([]int, len(e)); ix[0] < lens(0); NextIndex(ix, lens) {
var r []string
for j, k := range ix {
r = append(r, e[j][k])
}
fmt.Println(r)
}
}
输出结果为:
[a1 b1 c1 d1]
[a1 b1 c2 d1]
[a1 b1 c3 d1]
[a1 b2 c1 d1]
[a1 b2 c2 d1]
[a1 b2 c3 d1]
英文:
If you need an unknown-at-compile-time set of nested index loops, you can use code like this.
package main
import "fmt"
// NextIndex sets ix to the lexicographically next value,
// such that for each i>0, 0 <= ix[i] < lens(i).
func NextIndex(ix []int, lens func(i int) int) {
for j := len(ix) - 1; j >= 0; j-- {
ix[j]++
if j == 0 || ix[j] < lens(j) {
return
}
ix[j] = 0
}
}
func main() {
e := [][]string{
{"a1"},
{"b1", "b2"},
{"c1", "c2", "c3"},
{"d1"},
}
lens := func(i int) int { return len(e[i]) }
for ix := make([]int, len(e)); ix[0] < lens(0); NextIndex(ix, lens) {
var r []string
for j, k := range ix {
r = append(r, e[j][k])
}
fmt.Println(r)
}
}
The output is:
[a1 b1 c1 d1]
[a1 b1 c2 d1]
[a1 b1 c3 d1]
[a1 b2 c1 d1]
[a1 b2 c2 d1]
[a1 b2 c3 d1]
答案2
得分: 2
根据@paul-hankin的答案,这里有一个嵌入函数并使用泛型的解决方案。需要最低的go 1.18版本。
// cartesianProduct返回给定矩阵的笛卡尔积
func cartesianProduct[T any](matrix [][]T) [][]T {
// nextIndex将ix设置为字典序的下一个值,
// 对于每个i>0,0 <= ix[i] < lens(i)。
nextIndex := func(ix []int, lens func(i int) int) {
for j := len(ix) - 1; j >= 0; j-- {
ix[j]++
if j == 0 || ix[j] < lens(j) {
return
}
ix[j] = 0
}
}
lens := func(i int) int { return len(matrix[i]) }
results := make([][]T, 0, len(matrix))
for indexes := make([]int, len(matrix)); indexes[0] < lens(0); nextIndex(indexes, lens) {
var temp []T
for j, k := range indexes {
temp = append(temp, matrix[j][k])
}
results = append(results, temp)
}
return results
}
英文:
Based on @paul-hankin answer, here a solution which is embedded in a function and uses generics. Needs go 1.18 minimum
// cartesianProduct returns the cartesian product
// of a given matrix
func cartesianProduct[T any](matrix [][]T) [][]T {
// nextIndex sets ix to the lexicographically next value,
// such that for each i>0, 0 <= ix[i] < lens(i).
nextIndex := func(ix []int, lens func(i int) int) {
for j := len(ix) - 1; j >= 0; j-- {
ix[j]++
if j == 0 || ix[j] < lens(j) {
return
}
ix[j] = 0
}
}
lens := func(i int) int { return len(matrix[i]) }
results := make([][]T, 0, len(matrix))
for indexes := make([]int, len(matrix)); indexes[0] < lens(0); nextIndex(indexes, lens) {
var temp []T
for j, k := range indexes {
temp = append(temp, matrix[j][k])
}
results = append(results, temp)
}
return results
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论