如何计算可迭代对象的笛卡尔积

时间:2017-04-22 04:02:20

标签: javascript ecmascript-6

我正在寻找一种在EcmaScript 6中计算笛卡尔积的方法

示例:

product([["I", "They"], ["watch", "drink"], ["the sea", "the juice"]])

预期结果:

[["I", "watch", "the sea"], ["I", "watch", "the juice"], ["I", "drink", "the sea"], ["I", "drink", "the juice"], ["They", "watch", "the sea"], ["They", "watch", "the juice"], ["They", "drink", "the sea"], ["They", "drink", "the juice"]]

示例:

product([[-1, -2], [10, 20]])

预期结果:

[[-1, 10], [-1, 20], [-2, 10], [-2, 20]]

2 个答案:

答案 0 :(得分:2)

“假装JavaScript是Haskell”版本:

const re = g => a => ({
  [Symbol.iterator]: () => g(a)
})

const cons = x => re(function* (xs) {
  yield x
  yield* xs
})

const map = f => re(function* (xs) {
  for (const x of xs)
    yield f(x)
})

const ap = fs => re(function* (xs) {
  for (const f of fs)
    for (const x of xs)
      yield f(x)
})

const product = ([x, ...xs]) =>
  x ? ap(map(cons)(x))(product(xs)) :
      [[]]

使用如下(嗯,实际上不要):

for (const l of product([arr1, arr2, arr3]))
  callback(...l)

re使纯粹的生成器可重用。

答案 1 :(得分:1)

基于Ryan的想法:

let flatten = arr => [].concat(...arr);

function product([x, ...xs]) {
    if(!x) return [[]];

    let next = product(xs);

    return flatten(x.map(a =>
        next.map(b => [a, ...b])
    ));
}