# JavaScript中多个数组的笛卡尔积

``cartesian([1,2],[10,20],[100,200,300]) //should be // [[1,10,100],[1,10,200],[1,10,300],[2,10,100],[2,10,200]...]` `

` `function cartesianProductOf() { return _.reduce(arguments, function(a, b) { return _.flatten(_.map(a, function(x) { return _.map(b, function(y) { return x.concat([y]); }); }), true); }, [ [] ]); }; cartesianProductOf([1, 2], [3, 4], ['a', 'b']); // [[1,3,"a"],[1,3,"b"],[1,4,"a"],[1,4,"b"],[2,3,"a"],[2,3,"b"],[2,4,"a"],[2,4,"b"]]` `

` `function cartesianProduct(arr) { return arr.reduce(function(a,b){ return a.map(function(x){ return b.map(function(y){ return x.concat(y); }) }).reduce(function(a,b){ return a.concat(b) },[]) }, [[]]) } var a = cartesianProduct([[1, 2,3], [4, 5,6], [7, 8], [9,10]]); console.log(a);` `

` `function cartProd(paramArray) { function addTo(curr, args) { var i, copy, rest = args.slice(1), last = !rest.length, result = []; for (i = 0; i < args[0].length; i++) { copy = curr.slice(); copy.push(args[0][i]); if (last) { result.push(copy); } else { result = result.concat(addTo(copy, rest)); } } return result; } return addTo([], Array.prototype.slice.call(arguments)); } >> console.log(cartProd([1,2], [10,20], [100,200,300])); >> [ [1, 10, 100], [1, 10, 200], [1, 10, 300], [1, 20, 100], [1, 20, 200], [1, 20, 300], [2, 10, 100], [2, 10, 200], [2, 10, 300], [2, 20, 100], [2, 20, 200], [2, 20, 300] ]` `

anywho，enjoy -ck

# 2017更新：与香草JS的2行答案

` `let f = (a, b) => [].concat(...a.map(a => b.map(b => [].concat(a, b)))); let cartesian = (a, b, ...c) => b ? cartesian(f(a, b), ...c) : a;` `

### 更新：

` `const f = (a, b) => [].concat(...a.map(d => b.map(e => [].concat(d, e)))); const cartesian = (a, b, ...c) => (b ? cartesian(f(a, b), ...c) : a);` `

## 例

` `let output = cartesian([1,2],[10,20],[100,200,300]);` `

## 产量

` `[ [ 1, 10, 100 ], [ 1, 10, 200 ], [ 1, 10, 300 ], [ 1, 20, 100 ], [ 1, 20, 200 ], [ 1, 20, 300 ], [ 2, 10, 100 ], [ 2, 10, 200 ], [ 2, 10, 300 ], [ 2, 20, 100 ], [ 2, 20, 200 ], [ 2, 20, 300 ] ]` `

## 演示

• 与巴别的JS斌 （旧版浏览器）
• 没有巴别塔的JS Bin （适合现代浏览器）

## 不要像1995年那样编码

JavaScript的发展，这是有原因的。 TC39在语言设计方面做得非常出色，增加了新功能，浏览器厂商在实现这些功能方面做得非常出色。

` `function cartesianProduct(a) { // a = array of array var i, j, l, m, a1, o = []; if (!a || a.length == 0) return a; a1 = a.splice(0, 1)[0]; // the first array of a a = cartesianProduct(a); for (i = 0, l = a1.length; i < l; i++) { if (a && a.length) for (j = 0, m = a.length; j < m; j++) o.push([a1[i]].concat(a[j])); else o.push([a1[i]]); } return o; } console.log(cartesianProduct([[1,2], [10,20], [100,200,300]])); // [[1,10,100],[1,10,200],[1,10,300],[1,20,100],[1,20,200],[1,20,300],[2,10,100],[2,10,200],[2,10,300],[2,20,100],[2,20,200],[2,20,300]]` `

` `function* cartesian() { let arrays = arguments; function* doCartesian(i, prod) { if (i == arrays.length) { yield prod; } else { for (let j = 0; j < arrays[i].length; j++) { yield* doCartesian(i + 1, prod.concat([arrays[i][j]])); } } } yield* doCartesian(0, []); } console.log(JSON.stringify(Array.from(cartesian([1,2],[10,20],[100,200,300])))); console.log(JSON.stringify(Array.from(cartesian([[1],[2]],[10,20],[100,200,300]))));` `

` `function cartesianProduct(...arrays) { let current = new Array(arrays.length); return (function* backtracking(index) { if(index == arrays.length) yield current.slice(); else for(let num of arrays[index]) { current[index] = num; yield* backtracking(index+1); } })(0); } for (let item of cartesianProduct([1,2],[10,20],[100,200,300])) { console.log('[' + item.join(', ') + ']'); }` `
` `div.as-console-wrapper { max-height: 100%; }` `

` `function cartesianProduct(arr) { return arr.reduce((a, b) => a.map(x => b.map(y => x.concat(y))) .reduce((a, b) => a.concat(b), []), [[]]); } var arr = [[1, 2], [10, 20], [100, 200, 300]]; console.log(JSON.stringify(cartesianProduct(arr)));` `

` `_ = require("lodash") cartesianProduct = -> return _.reduceRight(arguments, (a,b) -> _.flatten(_.map(a,(x) -> _.map b, (y) -> x.concat(y)), true) , [ [] ])` `

` `Array.prototype.cartesian = function(...a){ return a.length ? this.reduce((p,c) => (p.push(...a[0].cartesian(...a.slice(1)).map(e => a.length > 1 ? [c,...e] : [c,e])),p),[]) : this; }; var arr = ['a', 'b', 'c'], brr = [1,2,3], crr = [[9],[8],[7]]; console.log(JSON.stringify(arr.cartesian(brr,crr)));` `

` `// Return cartesian product of given iterables: function* cartesian(head, ...tail) { const remaining = tail.length > 0 ? cartesian(...tail) : [[]]; for (let r of remaining) for (let h of head) yield [h, ...r]; } // Example: console.log(...cartesian([1, 2], [10, 20], [100, 200, 300]));` `

` `function crossproduct(arrays,rowtest,rowaction) { // Calculate the number of elements needed in the result var result_elems = 1, row_size = arrays.length; arrays.map(function(array) { result_elems *= array.length; }); var temp = new Array(result_elems), result = []; // Go through each array and add the appropriate element to each element of the temp var scale_factor = result_elems; arrays.map(function(array) { var set_elems = array.length; scale_factor /= set_elems; for(var i=result_elems-1;i>=0;i--) { temp[i] = (temp[i] ? temp[i] : []); var pos = i / scale_factor % set_elems; // deal with floating point results for indexes, this took a little experimenting if(pos < 1 || pos % 1 <= .5) { pos = Math.floor(pos); } else { pos = Math.min(array.length-1,Math.ceil(pos)); } temp[i].push(array[pos]); if(temp[i].length===row_size) { var pass = (rowtest ? rowtest(temp[i]) : true); if(pass) { if(rowaction) { result.push(rowaction(temp[i])); } else { result.push(temp[i]); } } } } }); return result; }` `

` `const _ = require('lodash') function combinations(arr, f, xArr = []) { return arr.length>1 ? _.flatMap(arr[0], x => combinations(arr.slice(1), f, xArr.concat(x))) : arr[0].map(x => f(...xArr.concat(x))) } // use case const greetings = ["Hello", "Goodbye"] const places = ["World", "Planet"] const punctuationMarks = ["!", "?"] combinations([greetings,places,punctuationMarks], (greeting, place, punctuationMark) => `\${greeting} \${place}\${punctuationMark}`) .forEach(row => console.log(row))` `

` `Hello World! Hello World? Hello Planet! Hello Planet? Goodbye World! Goodbye World? Goodbye Planet! Goodbye Planet?` `