【问题标题】:Cartesian product using reduce, map and spread is grouping the result which need to be flattened使用reduce、map和spread的笛卡尔积对需要展平的结果进行分组
【发布时间】:2016-10-02 18:27:10
【问题描述】:
class MathSet extends Set{
  constructor(arr){
     super(arr);
     }
  union(set){
     return new MathSet([...this, ...set])
  }
  intersection(set){
     return new MathSet([...this].filter(x => set.has(x)));
  }
  difference(set){
     return new MathSet([...this].filter(x => !set.has(x)));
  }
  cartesian(set){
     return new MathSet( [...this].reduce((acc, i)=> [...acc, [...set].map(j=>[i,j])], []) )
  }
}

let x = new MathSet([1,2,3]);
let y = new MathSet([1,2,3,4,5]);

console.log(JSON.stringify([...x.cartesian(y)]));
//[
//  [[1,1],[1,2],[1,3],[1,4],[1,5]],
//  [[2,1],[2,2],[2,3],[2,4],[2,5]],
//  [[3,1],[3,2],[3,3],[3,4],[3,5]]
// ]

使用cartesian 函数的预期结果是上述数组 ([[1,1],[1,2],[1,3],[1,4],[1,5],[2,1],[2,2],[2,3],[2,4],[2,5],[3,1],[3,2],[3,3],[3,4],[3,5]]) 的扁平化版本,但正如您所见,它以某种方式被分组为三个数组。 reduce 继续将早期结果与新结果的扩展版本连接起来。猜猜我做错了什么?

【问题讨论】:

  • 我知道这真的很让人头疼。我今天只是在处理这个。另一个令人头疼的问题是数组中的数组项。解决起来可能会有些混乱。

标签: javascript arrays ecmascript-6


【解决方案1】:

要使数组变平,您只需要再展开一次:

return new MathSet( [...this].reduce((acc, i)=> [...acc, ...[...set].map(j=>[i,j])], []) )
//                                                       ^^^

(或acc.concat(Array.from(set, j=>[i,j]))

【讨论】:

  • 这让我松了一口气!谢谢你:)
【解决方案2】:

这是个问题。我通过两个嵌套的 reduce 来做笛卡尔,就像处理两个数组一样,但实际上可以处理 n 个数组。主要问题是在操作之间将嵌套数组展平。我的解决方案是

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))); 

实际上,再考虑一下并通过您的代码的影响,我认为使用地图代替第二个 reduce 实际上更合适。我相应地修改了代码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-05-27
    • 2018-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多