放大过滤,和缩小过滤
If you ask a developer “What are some of the most important JavaScript array methods to know?”, you will likely hear mention of map
, filter
and reduce
. These 3 powerful methods enable you to iterate through the contents of an array, similar to using a for
loop. Each of these methods will create a new array (or element, object, etc. for reduce
) based on the callback function supplied, and they won’t mutate or change the original array.
如果您问开发人员“最重要JavaScript数组方法是什么?”,您可能会听到提到map
, filter
和reduce
。 这3种强大的方法使您可以遍历数组的内容,类似于使用for
循环。 这些方法中的每一个都会根据提供的回调函数创建一个新的数组(或用于reduce
元素,对象等),并且它们 不会变异或更改原始数组 。
Why should you use map
, filter
or reduce
instead of a for
loop?
为什么要使用map
, filter
或reduce
而不是for
循环?
- They can create code that’s easier to read. 他们可以创建更易于阅读的代码。
- They are quicker to write. 他们写得更快。
- They make it easy to chain methods together. 它们使将方法链接在一起变得容易。
- They aren’t destructive to the original array. 它们对原始数组没有破坏性。
In this article, I’m going to break down these 3 popular array methods.
在本文中,我将分解这3种流行的数组方法。
Array.map() (Array.map())
The map()
method invokes a callback function on every element in the array with an assigned value (not undefined), in order, and creates a brand new array composed of the results. The original array will not change. This method is helpful if you plan to use the new array for something, and if you wish to create a new value for every element in the array.
map()
方法将按顺序为数组中的每个元素分配一个分配了值(不是未定义)的回调函数,并创建一个由结果组成的全新数组。 原始数组不会更改。 如果您打算将新数组用于某些东西,并且希望为数组中的每个元素创建一个新值,则此方法很有用。
For example:
例如:
let array = [1, 2, 3, 4, 5]let newArray = array.map(element => element * 2)console.log(newArray) // [2, 4, 6, 8, 10]console.log(array) // [1, 2, 3, 4, 5]
It can also be written like this, where a function is named elsewhere and the function name is passed into map()
as the callback:
也可以这样写,其中一个函数在其他地方命名,该函数名作为回调传递给map()
:
let dogs = [
{name: "Missy", breed: "Pit mix"},
{name: "Cody", breed: "Havanese"},
{name: "Petunia", breed: "Shepherd Lab mix"},
{name: "Riley", breed: "🤷♀️"}
]const getDogInfo = function(dog) {
let info = [dog.name, " is a ", dog.breed].join(" ");
return info;
}let dogInfo = dogs.map(getDogInfo)console.log(dogInfo)
// ["Missy is a Pit mix",
// "Cody is a Havanese",
// "Petunia is a Shepherd Lab mix",
// "Riley is a 🤷♀️"]
The full syntax for map
is actually a bit longer, but under most use cases, we will only pass in the currentValue
(or element that we’re iterating on) and the callback function. According to MDN and W3Schools, the full syntax is this:
map
的完整语法实际上要更长一些,但是在大多数使用情况下,我们只会传递currentValue
(或我们要迭代的元素)和回调函数。 根据MDN和W3Schools ,完整语法是这样的:
array.map(function(currentValue, *index*, *arr*), *thisArg*)
// *optional*
The index
(of the current element being processed in the array), arr
(the array map
was called upon) and thisArg
(the value to use as this
when executing the callback
) are all optional arguments. When thisArg
is omitted, the value of this
will be considered undefined.
index
(数组中正在处理的当前元素的index
), arr
(调用了数组map
)和thisArg
(在执行callback
时用作this
值)都是可选参数。 当thisArg
被省略,值this
将被视为未定义。
You can read about more potential use cases of map()
here.
Array.filter() (Array.filter())
The filter()
method is similar to map()
as it also invokes a callback function on every element in the array with an assigned value, in order, and creates a brand new array without mutating the original. The new filtered array is composed of all the elements that return true for the callback function. Any elements in the original array that return false will be skipped. If there are no elements that return true, an empty array will be returned.
filter()
方法与map()
相似,因为它还会按顺序为数组中的每个元素分配一个具有分配值的回调函数,并创建一个全新的数组而不改变原始数组。 新的过滤数组由所有为回调函数返回true的元素组成。 原始数组中任何返回false的元素都将被跳过。 如果没有返回true的元素,则将返回一个空数组。
This method is great for (you guessed it) filtering out the elements you don’t want or need so that you’re left with just the desired ones in a new array.
该方法非常适合(您猜对了),过滤掉不需要或不需要的元素,以便在新数组中仅保留所需的元素。
For example:
例如:
let primates = ["gibbon", "gorilla", "bonobo", "pygmy marmoset", "cotton-top tamarin", "squirrel monkey", "howler monkey"]let apes = primates.filter(primate => primate.length <= 7 )
// clearly not how you determine an ape, just for demo purposes!!🙈console.log(apes) // ["gibbon", "gorilla", "bonobo"]
// but yes, these are apes 😉
Or another one, where the callback function is named elsewhere and passed in:
或另一个,其中回调函数在其他位置命名并传入:
let recipes = const findTastyFood = function(food) {
return !food.includes('mushroom')
// no mushrooms!! 🍄 🙅♀️ 🚫
}let tastyFoods = recipes.filter(findTastyFood)console.log(tastyFoods) // ["tempeh piccata", "vegan nachos", "tofu scramble", "kitchari", "pad thai", "zucchini pasta"]
// no gross mushrooms here! 👍
The full syntax for filter()
is very similar to map()
, and written with additional optional values as you see here:
filter()
的完整语法与map()
非常相似,并带有其他可选值,如下所示:
array.filter(function(currentValue, *index*, *arr*), *thisArg*)
// *optional*
Array.reduce() (Array.reduce())
The reduce()
method applies a function to each value of the array using an accumulator, and reduces the array to a single value. You can think of the accumulator as the “total” or “result” which each element in the array will be “added” to, similar to declaring let total = 0
with a function that iterates total += array[i]
. The accumulator can return many things, such as an array, an object or a number. As with map
and filter
, the original array with reduce
will remain unchanged.
reduce()
方法使用累加器将函数应用于数组的每个值,并将数组减少为单个值。 你可以想到 累加器是数组中每个元素将被“添加”到的“总计”或“结果”,类似于使用一个对total += array[i]
迭代的函数声明let total = 0
。 累加器可以返回很多东西,例如数组,对象或数字。 与map
和filter
,带有reduce
的原始数组将保持不变。
Here is the full syntax:
这是完整的语法:
array.reduce(function(accumulator, currentValue, *index*, *arr*), *initialValue*)
// *optional*
The index
, arr
and initialValue
are all optional values, like with map
and filter
, but it’s often recommended to include the initialValue
. If one is provided, then the accumulator
(total) will be equal to the initialValue
, and the currentValue
will be equal to the first element in the array. If an initialValue
isn’t provided, the first element of the array will be considered the accumulator
and the second element will become the currentValue
. (MDN)
index
, arr
和initialValue
都是可选值,就像map
和filter
,但是通常建议包含initialValue
。 如果提供一个,则accumulator
(总计)将等于initialValue
,而currentValue
将等于数组中的第一个元素。 如果未提供initialValue
,则数组的第一个元素将被视为accumulator
,第二个元素将成为currentValue
。 ( MDN )
For example, without an initialValue
:
例如,没有initialValue
:
let sum = [0, 1, 2, 3, 4].reduce(
(accumulator, currentValue, currentIndex, array) =>
accumulator + currentValue )console.log(sum) // 10
The iteration will look like this, with a final sum of 10:
迭代看起来像这样,最终的总和为10:
But if we provide an initialValue
of 10:
但是,如果我们提供的initialValue
为10:
let sum = [0, 1, 2, 3, 4].reduce(
(accumulator, currentValue, currentIndex, array) => {
return accumulator + currentValue
}, 10)console.log(sum) // 20
Then we will start at 10, and add each element in the array from there, giving a final sum of 20:
然后我们从10开始,然后从那里添加数组中的每个元素,最终总和为20:
The reduce
method can have many uses, and is helpful for condensing information outside of the math spectrum as well. If you ever find yourself chaining map
and filter
for example, you could replace these 2 methods with reduce
, resulting in less traversing and additionally less time complexity.
reduce
方法可以有很多用途,并且也有助于在数学范围之外压缩信息。 例如,如果您发现自己链接map
和filter
,则可以将这两种方法替换为reduce
,从而减少遍历和时间复杂度。
Here’s one more example:
这是另一个示例:
let fruits = ['🍊', '🍐', '🍓', '🍇', '🍒', '🍊', '🍇']
let countedFruit = fruits.reduce(function (allFruit, fruit) {
if (fruit in allFruit) {
allFruit[fruit]++
}
else {
allFruit[fruit] = 1
}
return allFruit
}, {})console.log(countedFruit) //
There are many more use cases for all 3 of these methods, and further examples can be found at MDN, Digital Ocean and more.
所有这三种方法的用例更多,并且可以在MDN , Digital Ocean等网站上找到更多示例。
Happy coding!
编码愉快!
翻译自: https://medium.com/javascript-in-plain-english/how-to-use-map-filter-and-reduce-5b512e6ad3c6
放大过滤,和缩小过滤