如何打破reduce方法

Jul*_*ins 68 javascript reduce loops

如何在reduce方法上打破迭代?

对于

for (var i = Things.length - 1; i >= 0; i--) {
  if(Things[i] <= 0){
    break;
  }
};
Run Code Online (Sandbox Code Playgroud)

降低

Things.reduce(function(memo, current){
  if(current <= 0){
    //break ???
    //return; <-- this will return undefined to memo, which is not what I want
  }
}, 0)
Run Code Online (Sandbox Code Playgroud)

Tob*_*Rex 70

UPDATE

一些评论员提出了一个很好的观点,即原始数组正在被改变,以便在.reduce()逻辑内部尽早打破.

因此,我在调用后续步骤之前添加了一个,稍微修改了答案. .slice(0).reduce()

这是通过以线性时间 - O(n)复制其内容来保留原始数组.原始数组也会记录到控制台,以证明它已被保留.

const array = ["9", "91", "95", "96", "99"];
const x = array.slice(0).reduce((acc, curr, i, arr) => {  // notice the "slice(0)"
 if (i === 2) arr.splice(1); // eject early
 return (acc += curr);
}, "");
console.log("x: ", x, "\noriginal Arr: ", array); // x:  99195
// original Arr:  [ '9', '91', '95', '96', '99' ]
Run Code Online (Sandbox Code Playgroud)

您可以通过改变reduce函数的第四个参数:"array"来中断.reduce()调用的任何迭代.无需自定义缩减功能.有关参数的完整列表,请参阅文档.reduce().

Array.prototype.reduce((acc,curr,i,array))

第四个参数是迭代的数组.

const array = ['9', '91', '95', '96', '99'];
const x = array
.reduce((acc, curr, i, arr) => {
    if(i === 2) arr.splice(1);  // eject early
    return acc += curr;
  }, '');
console.log('x: ', x);  // x:  99195
Run Code Online (Sandbox Code Playgroud)

为什么?:

我可以想到使用它而不是提供许多其他解决方案的唯一原因是,如果您想要为您的算法维护一种函数式编程方法,并且您希望最具声明性的方法可以实现这一点.如果你的整个目标是将一个数组简化为一个备用的非假名原语(String,Number,Boolean,Symbol),那么我认为这实际上是最好的方法.

为什么不?

有一个完整的参数列表可以使NOT变异函数参数,因为这是一个不好的做法.

  • +1.这应该是公认的答案.但是,由于"为什么不",所以不应该使用此解决方案. (3认同)
  • 这真是个不好的建议,因为`splice`执行一个可见的变异(`array`).根据功能范例,您可以使用延迟传递风格的减少或使用右关联减少的惰性评估.或者,作为一个更简单的替代方案,只是简单的递归. (3认同)
  • 我更喜欢使用扩展运算符来避免任何不需要的突变,[...array].reduce() (2认同)

Rob*_*obG 10

只要您不关心返回值,就可以使用像someevery这样的函数.每次回调时返回false休息,有的时候返回true:

things.every(function(v, i, o) {
  // do stuff 
  if (timeToBreak) {
    return false;
  } else {
    return true;
  }
}, thisArg);
Run Code Online (Sandbox Code Playgroud)

  • 但是,如果他试图做"减少",那么根据定义他**会关心回报价值. (17认同)

小智 7

当然,没有办法让内置版本reduce过早退出.

但是你可以编写自己的reduce版本,它使用一个特殊的标记来识别循环应该被打破的时间.

var EXIT_REDUCE = {};

function reduce(a, f, result) {
  for (let i = 0; i < a.length; i++) {
    let val = f(result, a[i], i, a);
    if (val === EXIT_REDUCE) break;
    result = val;
  }
  return result;
}
Run Code Online (Sandbox Code Playgroud)

像这样使用它来对数组求和但是当你达到99时退出:

reduce([1, 2, 99, 3], (a, b) => b === 99 ? EXIT_REDUCE : a + b, 0);

> 3
Run Code Online (Sandbox Code Playgroud)


And*_*Dev 7

不要使用减少.只需使用普通迭代器(等等)迭代数组,并在满足条件时突破.

  • 这有什么好玩的?:) (14认同)
  • 不知道为什么这得到了很多赞成票...这是一个非答案,因为OP询问如何尽早从reduce()中中断..这就像当你弯腰时感到疼痛时去看医生,医生告诉你你不要弯腰。 (4认同)
  • 是的,可以通过解释为什么如果需要打破循环,使用函数式编程可能不是最佳实践来改进这个答案。人们会假设OP完全了解基本迭代器,也许他们只是想避免污染范围,谁知道呢。 (2认同)

Dou*_*urn 5

Array.every 可以提供一种非常自然的机制来打破高阶迭代。

const product = function(array) {
    let accumulator = 1;
    array.every( factor => {
        accumulator *= factor;
        return !!factor;
    });
    return accumulator;
}
console.log(product([2,2,2,0,2,2]));
// 0
Run Code Online (Sandbox Code Playgroud)