summaryrefslogtreecommitdiffstats
path: root/pkg/common/cartesian.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/common/cartesian.go')
-rw-r--r--pkg/common/cartesian.go54
1 files changed, 54 insertions, 0 deletions
diff --git a/pkg/common/cartesian.go b/pkg/common/cartesian.go
new file mode 100644
index 0000000..9cd6065
--- /dev/null
+++ b/pkg/common/cartesian.go
@@ -0,0 +1,54 @@
+package common
+
+// CartesianProduct takes map of lists and returns list of unique tuples
+func CartesianProduct(mapOfLists map[string][]interface{}) []map[string]interface{} {
+ listNames := make([]string, 0)
+ lists := make([][]interface{}, 0)
+ for k, v := range mapOfLists {
+ listNames = append(listNames, k)
+ lists = append(lists, v)
+ }
+
+ listCart := cartN(lists...)
+
+ rtn := make([]map[string]interface{}, 0)
+ for _, list := range listCart {
+ vMap := make(map[string]interface{})
+ for i, v := range list {
+ vMap[listNames[i]] = v
+ }
+ rtn = append(rtn, vMap)
+ }
+ return rtn
+}
+
+func cartN(a ...[]interface{}) [][]interface{} {
+ c := 1
+ for _, a := range a {
+ c *= len(a)
+ }
+ if c == 0 || len(a) == 0 {
+ return nil
+ }
+ p := make([][]interface{}, c)
+ b := make([]interface{}, c*len(a))
+ n := make([]int, len(a))
+ s := 0
+ for i := range p {
+ e := s + len(a)
+ pi := b[s:e]
+ p[i] = pi
+ s = e
+ for j, n := range n {
+ pi[j] = a[j][n]
+ }
+ for j := len(n) - 1; j >= 0; j-- {
+ n[j]++
+ if n[j] < len(a[j]) {
+ break
+ }
+ n[j] = 0
+ }
+ }
+ return p
+}