是否有更多的“函数式编程”方法来解决这个问题而不使用`forEach`?

时间:2017-01-24 01:28:43

标签: javascript foreach functional-programming

我听说过,使用新的(或至少更好的)JavaScript语言选项,我们不再需要使用forEach了。我想知道这是否是提倡函数式编程的间接方式。我最近遇到了一个数组操作算法,需要嵌套使用forEach,并想知道是否有一种更实用的方法来解决问题。我能够使用reduce重新编写代码,但最终比forEach解决方案更长。就其本身而言,稍微长一点的代码可能不会“糟糕”,但这确实让我想知道是否有更好的方法可以使用函数式编程来解决这个问题。

问题如下:重新处理数组数组以生成所有原始元素的扁平数组,但每个新元素现在与它来自的原始子数组的数量配对。例如将[[8,2,4],[5],[1,7]]转换为[[8,0],[2,0],[4,0],[5,1],[1,2],[7,2]]

(为了让读者理解这个问题的许多初步批评意见,问题的原始措辞集中在使代码更短。我的真实意图是询问更好的方法来解决这个问题。问题,导致上面重新措辞的问题。)

const oldArr = [[8,2,4],[5],[1,7]];

const newArr1 = [];
oldArr.forEach((subArr, subArrNum) => {
  subArr.forEach(elmt => {newArr1.push([elmt, subArrNum]);});
});

const newArr2 = oldArr.reduce((accum1, subArr, subArrNum) => accum1.concat(
  subArr.reduce((accum2, elmt) => accum2.concat([[elmt, subArrNum]]), [])
), []);

console.log(JSON.stringify(newArr1));
console.log(JSON.stringify(newArr2));

// for the sake of comparing code length, here are the exact same two
// solutions using only single letter variable names with each solution
// compressed onto a single line:

const o = oldArr;
let x,y;

x=[];o.forEach((s,n)=>{s.forEach(e=>{x.push([e,n]);});});

y=o.reduce((a,s,n)=>a.concat(s.reduce((b,e)=>b.concat([[e,n]]),[])),[]);

console.log(JSON.stringify(x));
console.log(JSON.stringify(y));

1 个答案:

答案 0 :(得分:0)

在对该问题的评论中,@ Ryan提供了一个解决方案,在下面的代码中标记为newArray1,而@Potter提供了一个“babel-safe”变体,标记为newArray2(带有次要内容)变量名称的更改和括号的删除使这两个函数更容易比较):

const o = [[8,2,4],[5],[1,7]];

const newArray1 = [].concat      (   ...o.map((x,i)=>x.map(y=>[y,i])));
const newArray2 = [].concat.apply([],   o.map((x,i)=>x.map(y=>[y,i])));

console.log(JSON.stringify(newArray1));
console.log(JSON.stringify(newArray2));

我认为在这个解决方案中减少混乱使得它比我原来的功能解决方案更容易理解。

但是,请注意,Ryan还在进一步评论该方法的问题时提出了问题。他写道[].concat(...x)(并且,我认为,也是它的“babel-safe”变体)“......可能导致堆栈溢出,一个;尝试[].concat(...Array(1000000))。理想情况下会有一个内置的const concat = arrs => arrs.reduce((m, n) => m.concat(n), []);的行(但可能更有效)。“