Javascript 何时/为什么使用 map/reduce over for 循环

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29640254/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 03:42:32  来源:igfitidea点击:

When/why to use map/reduce over for loops

javascript

提问by

So I am getting into a bit of object manipulation in JavaScript for the first time and I have a question I'm wondering if anyone could answer.

所以我第一次在 JavaScript 中进行了一些对象操作,我有一个问题,我想知道是否有人可以回答。

When I have an object I want to manipulate I could do something to the extent of a few nested for loops, however there are functions built into JavaScript, like map/reduce/filter, and libraries like lodash/underscore.

当我有一个想要操作的对象时,我可以在一些嵌套的 for 循环范围内做一些事情,但是 JavaScript 中内置了一些函数,如 map/reduce/filter,以及 lodash/underscore 等库。

I assume the latter (map/reduce/filter and the libraries) are better practice but I'm just curious as to why.

我认为后者(map/reduce/filter 和库)是更好的做法,但我只是好奇为什么。

I am doing some pretty basic object manipulation that could be solved with a few well placed for loops to grab and change the right keys/values in the object, but can be easily done with the functions/libraries in JS. Just curious as to how they are better - like better performance/cleaner code/ease of use/whatever else.

我正在做一些非常基本的对象操作,可以通过一些放置良好的 for 循环来解决,以获取和更改对象中正确的键/值,但可以使用 JS 中的函数/库轻松完成。只是好奇它们如何更好 - 比如更好的性能/更干净的代码/易用性/其他任何东西。

Apologies, there is no code. I would very much appreciate anyone helping me understand more here.

抱歉,没有代码。我将非常感谢任何帮助我在这里了解更多的人。

Edit - so taking from the examples for map()

编辑 - 所以从 map() 的例子中获取

I could take the example for javascript.map

我可以以 javascript.map 为例

 var kvArray = [{key:1, value:10}, {key:2, value:20}, {key:3, value: 30}];
var reformattedArray = kvArray.map(function(obj){ 
var rObj = {};
rObj[obj.key] = obj.value;
return rObj;
});

I could do something like

我可以做类似的事情

   var kvArray = [{key:1, value:10}, {key:2, value:20}, {key:3, value: 30}];
var reformattedArray = [];

for(var object in kvArray){
  //combine both values into object inside of kvArray[object]);
 };

A lot less code - but any other benefits worth knowing about?

代码少了很多 - 但还有其他值得了解的好处吗?

回答by Naresh Kumar

I know I'm replying to an old answer but just wanted to point out for future readers.

我知道我正在回复一个旧答案,但只是想为未来的读者指出。

Map reduce and filter functions come from the functional programming world.

Map reduce 和 filter 函数来自函数式编程世界。

These are first class built-in operators in languages like Lisp, Haskell, and others(ml?). Functional languages tend to prefer to run operators over immutable data than make the code run over the data to operate on it (say loops). So they provide simpler but powerful interfaces like map, filter and reduce when compared to providing for and while loops.

这些是 Lisp、Haskell 等语言中的一流内置运算符(ml?)。函数式语言倾向于在不可变数据上运行运算符,而不是让代码在数据上运行以对其进行操作(例如循环)。因此,与提供 for 和 while 循环相比,它们提供了更简单但功能强大的接口,例如 map、filter 和 reduce。

It also helps them satisfy other requirements like immutability etc. That's why maps give u back a new map instead of mutating the old one. These are very good from a concurrency point of view, though they may be slower in certain contexts.

它还可以帮助他们满足其他要求,如不变性等。这就是为什么地图给你一张新地图而不是改变旧地图的原因。从并发的角度来看,这些非常好,尽管在某些情况下它们可能会更慢。

This approach usually leads to fewer errors in code in multi-threaded or high concurrency apps. When multiple actors act on the same piece of data, immutability helps keep code from stepping on each other's toes.

这种方法通常会减少多线程或高并发应用程序中的代码错误。当多个参与者对同一条数据进行操作时,不变性有助于防止代码相互影响。

Since javascript tries to be partially functional by providing some functionalities of functional programming languages, it might have made sense to implement map, filter and reduce functions in it too.

由于 javascript 试图通过提供函数式编程语言的一些功能来实现部分功能,因此在其中实现 map、filter 和 reduce 函数可能是有意义的。

YMMV depending on what you are doing with the tools you are given.

YMMV 取决于您使用所提供的工具做什么。

If your code works better with a for loop, go for it.

如果您的代码使用 for 循环效果更好,那就去吧。

But if you ever find asynchronous code munching on common data and you end up splitting your hairs trying to debug a loop. Say hi, to map, reduce and filter.

但是,如果您发现异步代码正在咀嚼公共数据,并且最终会在尝试调试循环时分心。打个招呼,映射,减少和过滤。

回答by jfriend00

.map()allows you to create a new array by iterating over the original array and allowing you to run some sort of custom conversion function. The output from .map()is a new array.

.map()允许您通过迭代原始数组并允许您运行某种自定义转换函数来创建新数组。的输出.map()是一个新数组。

var orig = [1,2,3,4,5];
var squares = orig.map(function(val) {
    return val * val;
});
console.log(squares);   // [1,4,9,16,25]


.reduce()allows you to iterate over an array accumulating a single result or object.

.reduce()允许您迭代累积单个结果或对象的数组。

var orig = [1,2,3,4,5];
var sum = orig.reduce(function(cum, val) {
    return cum + val;
}, 0);
console.log(sum);    // 15

These are specialized iterators. You can use them when this type of output is exactly what you want. They are less flexible than a forloop (for example, you can't stop the iteration in the middle like you can with a forloop), but they are less typing for specific types of operations and for people that know them, they are likely a little easier to see the code's intent.

这些是专门的迭代器。当这种类型的输出正是您想要的时,您可以使用它们。它们不如for循环灵活(例如,您不能像使用for循环那样在中间停止迭代),但是它们对于特定类型的操作和了解它们的人的输入较少,它们很可能是更容易看出代码的意图。

I have not myself tested the performance of .map()and .reduce()versus a forloop, but have seen tests for .forEach()which showed that .forEach()was actually slower in some browsers. This is perhaps because each iteration of the loop with .forEach()has to call your callback function, whereas in a plain forloop, you do not have to make such a function call (the code can be directly embedded there). In any case, it is rare that this type of performance difference is actually meaningful and you should generally use whichever construct makes clearer, easier to maintain code.

我自己还没有测试过.map()and.reduce()for循环的性能,但已经看到测试.forEach()表明它.forEach()在某些浏览器中实际上更慢。这可能是因为循环的每次迭代.forEach()都必须调用您的回调函数,而在普通for循环中,您不必进行这样的函数调用(代码可以直接嵌入其中)。无论如何,这种类型的性能差异很少真正有意义,您通常应该使用使代码更清晰、更易于维护的构造。

If you really wanted to optimize performance, you would have to write your own test case in a tool like jsperf and then run it in multiple browsers to see which way of doing things was best for your particular situation.

如果您真的想优化性能,则必须在 jsperf 之类的工具中编写自己的测试用例,然后在多个浏览器中运行它,以查看哪种处理方式最适合您的特定情况。



Another advantage of a forloop is that it can be used with array-like objects such as an HTMLCollection which are not actual arrays and thus don't have methods like .reduce()and .map().

for循环的另一个优点是它可以与类似数组的对象一起使用,例如 HTMLCollection,这些对象不是实际的数组,因此没有像.reduce()and这样的方法.map()

回答by Lloyd Banks

This is like asking if I like basketball or football better. Both have their positives.

这就像问我更喜欢篮球还是足球。两者都有其积极的一面。

If you have 10 developers look at your for loop, 9 out of 10 will know what you are doing right away. Maybe half will have to look up what the map()method is, but then they'll also know what's going on. So in this respect, a for loop is easier for others to read.

如果您有 10 个开发人员查看您的 for 循环,那么 10 个中有 9 个会立即知道您在做什么。也许一半的人将不得不查找map()方法是什么,但他们也会知道发生了什么。所以在这方面,for 循环更容易被其他人阅读。

On the flip side, map()will save you two or three lines of code.

另一方面,map()将为您节省两三行代码。

As far as performance goes, you'll find map()is built internally with something akin to a for loop. You might see a few milliseconds of difference when it comes to performance speeds if you run them through large iterations; but they'll never be recognizable to an end user.

就性能而言,您会发现它map()是在内部构建的,类似于 for 循环。如果您通过大型迭代运行它们,您可能会发现性能速度有几毫秒的差异;但最终用户永远无法识别它们。

回答by Juanma Menendez

forEach(): Executes a provided function(callback) once for each array element. Doesn't return anything (undefined) but this callback is allowed to mutate the calling array.

forEach():为每个数组元素执行一次提供的函数(回调)。不返回任何内容(undefined),但允许此回调改变调用数组。

map(): Executes a provided function(callback) once for each array element and creates a new array with the results of this executions. It cannot mutate the calling array content.

map():为每个数组元素执行一次提供的函数(回调),并使用此执行的结果创建一个新数组。它不能改变调用数组的内容。

ConclutionUse map()when you need to return a new array, use forEach()or forwhen you want to change the original array.

结论使用map(),当你需要返回一个新的数组,使用forEach()for当你想改变原来的数组。

回答by Anand N

Bumped into this while searching for something else. So trying to answer it even if it is a old thread as the concepts applies no matter what.

在寻找其他东西时遇到了这个问题。因此,即使它是一个旧线程,也要尝试回答它,因为无论如何这些概念都适用。

If you consider performance and flexibility, "for" loop always beats the others, just because it doesn't have the overhead of calling a function for each iteration and can be used for any purpose.

如果考虑性能和灵活性,“for”循环总是胜过其他循环,因为它没有为每次迭代调用函数的开销,并且可以用于任何目的。

But, there are other gains with functions like forEach, map, reduce etc (let's call them functional methods). It is mainly the readability, maintainability.

但是,使用 forEach、map、reduce 等函数还有其他好处(让我们称它们为函数式方法)。它主要是可读性、可维护性。

Below are few drawbacks of for loop

以下是 for 循环的一些缺点

  1. Introduces new variables to the scope, just for the counter/iteration
  2. Hard to debug errors, due to un-intentional changes to counter variables. This becomes more difficult and the chances to make a mistake increases more as the number of loops with in loops increase
  3. Developers have the habit of using loop variables as i, j, k. It is very easy to lose the track of which counter and which inner loop the code is executing once the loop increases certain lines of code
  4. With ES6, we have at least limited/local scope introduced by 'let'. But before, the variables introduced by for loop have a function scope causing even more accidental errors
  1. 向作用域引入新变量,仅用于计数器/迭代
  2. 由于对计数器变量的无意更改,难以调试错误。随着 in 循环次数的增加,这变得更加困难,并且犯错的机会也会增加
  3. 开发者有使用循环变量作为 i、j、k 的习惯。一旦循环增加了某些代码行,就很容易忘记代码正在执行哪个计数器和哪个内循环
  4. 在 ES6 中,我们至少有 'let' 引入的有限/局部范围。但是之前for循环引入的变量有一个函数作用域导致更多的意外错误

To avoid all of these, it is suggested to use functions like forEach, map, reduce when you know what you have to do (Not to forget most of these functional methods offer immutability). A small sacrifice in terms of performance for the greater good and more succinct code.

为了避免所有这些,建议在您知道必须做什么时使用诸如 forEach、map、reduce 之类的函数(不要忘记这些函数方法中的大多数都提供了不变性)。为了更好和更简洁的代码,在性能方面略有牺牲。

With ES6, most of the functional methods are supported by the language itself. They are optimised and we don't have to rely on libraries like lodash (unless there is a severe performance gain).

在 ES6 中,大多数函数式方法都由语言本身支持。它们经过优化,我们不必依赖像 lodash 这样的库(除非有严重的性能提升)。

回答by Rahul Dwivedi

Just bumped into this and found that none of the answers highlights one important difference between for-loopand mapas to when to use one over the other:

刚刚碰到这个,发现没有一个答案突出了一个重要的区别,for-loop以及map何时使用另一个:

  1. With mapyou can't break out of an iteration which you can with for-loop.
  1. 有了map你就无法突破迭代,而for-loop.

For e.g, you can't do this

例如,你不能这样做

const arr = [5, 6, 9, 4];
arr.map(elem=>{
   if(elem === 5){
     break; //This is not allowed
  }
})