简体   繁体   English

Array.prototype.reduce与一个简单的for循环,用于过滤和修改数据

[英]Array.prototype.reduce vs a simple for loop for filtering and modifying data

"Reducing Filter and Map Down to Reduce" by Elijah Manor outlines the following use case for Array.prototype.reduce() : Elijah Manor的“减少过滤器并向下映射以减少”概述了Array.prototype.reduce()的以下用例:

Given the following data (from the linked article): 给定以下数据(来自链接的文章):

var doctors = [
    { number: 1,  actor: "William Hartnell",      begin: 1963, end: 1966 },
    { number: 2,  actor: "Patrick Troughton",     begin: 1966, end: 1969 },
    { number: 3,  actor: "Jon Pertwee",           begin: 1970, end: 1974 },
    { number: 4,  actor: "Tom Baker",             begin: 1974, end: 1981 },
    { number: 5,  actor: "Peter Davison",         begin: 1982, end: 1984 },
    { number: 6,  actor: "Colin Baker",           begin: 1984, end: 1986 },
    { number: 7,  actor: "Sylvester McCoy",       begin: 1987, end: 1989 },
    { number: 8,  actor: "Paul McGann",           begin: 1996, end: 1996 },
    { number: 9,  actor: "Christopher Eccleston", begin: 2005, end: 2005 },
    { number: 10, actor: "David Tennant",         begin: 2005, end: 2010 },
    { number: 11, actor: "Matt Smith",            begin: 2010, end: 2013 },
    { number: 12, actor: "Peter Capaldi",         begin: 2013, end: 2013 }    
];

We can both modify and filter the data at the same time using .reduce() as shown below (also from the linked article): 我们可以使用.reduce()同时修改和过滤数据,如下所示(同样来自链接的文章):

doctors = doctors.reduce(function(memo, doctor) {
    if (doctor.begin > 2000) { // this serves as our `filter`
        memo.push({ // this serves as our `map`
            doctorNumber: "#" + doctor.number,
            playedBy: doctor.actor,
            yearsPlayed: doctor.end - doctor.begin + 1
        });
    }
    return memo;
}, []);

However, why would one prefer this over a simple for loop? 但是,为什么会比简单的for循环更喜欢呢? I doubt it out-performs a simple iterating loop with similar contents (though I can't test that claim since Jsperf is down ). 我怀疑它的性能优于具有相似内容的简单迭代循环(尽管由于Jsperf down ,所以我无法测试该声明)。

Is there any reason (performance or otherwise) to use the .reduce() implementation over a simple loop, other than syntax preference? 除了语法首选项之外,是否有任何理由(性能或其他方式)在简单的循环上使用.reduce()实现?

One objective benefit of array operations like map or reduce is the inherent variable scoping and reduction of boilerplate code. mapreduce这样的数组操作的一个客观好处是固有的变量作用域和样板代码的减少。 Compare: 相比:

var result = 0;
for (var i = 0, length = arr.length; i < length; i++) {
    result += arr[i];
}

// vs:

var result = arr.reduce(function (acc, val) { return acc + val; }, 0);

The giant loop declaration has nothing inherently to do with what you're trying to do here, it's just boilerplate code. 巨型循环声明与您在此处尝试执行的操作本质上无关,只是样板代码。 Further, your scope now has two additional variables i and length floating around which nobody asked for, which may or may not introduce some non-obvious bugs if you're not careful. 此外,您的作用域现在还有两个其他变量ilength浮动,没有人在周围询问,如果您不小心的话,可能会或可能不会引入一些非显而易见的错误。

The reduce code on the other hand just contains the minimum necessary parts to do what it needs to do. 另一方面, reduce代码仅包含执行所需操作所需的最少部分。 In something like CoffeeScript its syntax can even further be reduced to arr.reduce (acc, val) -> acc + val , which is pretty darn concise. 在类似CoffeeScript之类的东西中,其语法甚至可以进一步简化为arr.reduce (acc, val) -> acc + val ,这arr.reduce (acc, val) -> acc + val简明了。 And even if you'd need to create additional variables during the operation inside the loop/the callback, those won't clutter the outer scope. 并且即使您需要在循环/回调内部的操作过程中创建其他变量,这些变量也不会使外部范围混乱。

Secondarily, reduce is a well known paradigm and serves as a good statement of intend for that code block. 其次, reduce是众所周知的范例,可以很好地说明该代码块的意图。 You don't need to parse useless auxiliary variables and figure out what they're for, you can simply break down the operation into what array is being operated on ( arr ) and what result the callback expression ( acc + val ) will produce, then extrapolate that over the entire array to know what the result will be. 您无需解析无用的辅助变量并弄清楚它们的用途,您只需将操作分解为要对哪个数组进行操作( arr )以及回调表达式( acc + val )会产生什么结果,然后在整个数组上外推,以了解结果。

Potentially such operations can also be better optimised by a compiler under certain circumstances, but this is mostly not seen in practice at this time I believe. 这种潜在的操作也可以更好地在某些情况下编译器优化,但是这主要是在实践中没有在这个时候,我相信看到。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM