定义
笛卡尔积一般表示为公式:X * Y
, 主要描述两个集合中元素所有可能的组合。
例如集合 {1, 2}
和 {x, y}
其笛卡尔积为 [{1, x}, {1, y}, {2, x}, {2, y}]
。
结果集长度为len(X) * len(Y)
计算思路
假设需要计算三个集合 a * b * c
的笛卡尔积,根据笛卡尔积公式。计算步骤可拆分如下:
- 计算
x = a * b
- 计算
x * c
例如 a = {"1", "2"}
, b = {"a", "b"}
, c = {"X", "Y"}
- 计算
x = a * b
, 结果为
[["1", "a"], ["1", "b"], ["2", "a"], ["2", "b"]]
- 计算
x * c
, 结果为
[
["1", "a", "X"], ["1", "a", "Y"],
["1", "b", "X"], ["1", "b", "Y"],
["2", "a", "X"], ["2", "a", "Y"],
["2", "b", "X"], ["2", "b", "Y"],
]
计算任意多集合笛卡尔积时也是这个思路,按顺序分别计算相邻两个集合笛卡尔积(分治)
示例代码
var (
a = []string{"a", "b"}
b = []string{"1", "2"}
c = []string{"X", "Y"}
d = []string{"!", "@"}
)
有a,b,c,d
4个集合,计算其笛卡尔积.
字符串版
package main
import "fmt"
var (
a = []string{"a", "b"}
b = []string{"1", "2"}
c = []string{"X", "Y"}
d = []string{"!", "@"}
)
func CartesianProductStr(strSets ...[]string) []string {
orig := strSets[0] // 拆分第一个数组作为起始数组
for _, other := range strSets[1:] {
orig = merge(orig, other)
}
return orig
}
// merge 计算笛卡尔积
func merge(xs, ys []string) []string {
item := make([]string, 0)
for _, x := range xs {
for _, y := range ys {
item = append(item, x+y)
}
}
return item
}
func main() {
fmt.Println(CartesianProductStr(a, b, c, d))
}
// 输出结果:
// [a1X! a1X@ a1Y! a1Y@ a2X! a2X@ a2Y! a2Y@ b1X! b1X@ b1Y! b1Y@ b2X! b2X@ b2Y! b2Y@]
数组版
func CartesianProductArray(strSets ...[]string) [][]string {
// 拆分第一个数组作为起始数组
orig := make([][]string, len(strSets[0]))
for idx, item := range strSets[0] {
orig[idx] = []string{item}
}
for _, other := range strSets[1:] {
orig = mergeArray(orig, other)
}
return orig
}
// merge 计算笛卡尔积
func mergeArray(xs [][]string, ys []string) [][]string {
item := make([][]string, 0)
for _, x := range xs {
for _, y := range ys {
item = append(item, append(x, y))
}
}
return item
}
func main() {
fmt.Println(CartesianProductArray(a, b, c, d))
}
// 输出结果:
// [[a 1 X @] [a 1 X @] [a 1 Y @] [a 1 Y @] [a 2 X @] [a 2 X @] [a 2 Y @] [a 2 Y @] [b 1 X @] [b 1 X @] [b 1 Y @] [b 1 Y @] [b 2 X @] [b 2 X @] [b 2 Y @] [b 2 Y @]]