Javascript Array中的filter、map和reduce
前幾天寫了篇文章科普了下Javascript中 Array.filter() 的妙用,后來無意間發現了 一篇好文章 ,一次性科普了三個API: filter 、 map 和 reduce ,生動形象,尤其是配圖,顯然是用了心思。下面是譯文:
最近,一直在為一個客戶做一個視覺化數據的項目,從服務端API拉取數據回來然后轉換出視覺效果,自然少不了大量的數據操作,為此我一再使用Javascript中的Array 三個API:filter、map 和 reduce 。
Map 、 Filter 和 Reduce 常常被用于對一個數組做一些操作,進而轉換成某個新的東西(數據類型不一定還是數組哦~)。下面是我對這三個API的直觀認識:
Map

你想將一個數組中的每一項做個轉換,結果生成了一個新數組,并且新數組的長度和原數組一致。
Filter

你想將一個數組做一個過濾,按照某規則提取出一些特定的項來。結果也生成了一個新數組,但新數組的長度小于或等于原數組。
Reduce

你想通過遍歷一個數組的每一項來計算出一個新東西,最后生成的結果可以是任何類型的變量:一個新數組,一個新對象,一個新布爾值…
filter 、 map 和 reduce 共同點就是并不會對原數組做任何改動,結果都是生成一個新變量。讓我們來看一些例子:
Array.map()
現在我們有一個對象列表,其中每個對象代表的是一種變形金剛(譯注:看來這位歪果仁是個變形金剛粉絲):
var transformers = [
{
name: 'Optimus Prime',
form: 'Freightliner Truck',
team: 'Autobot'
},
{
name: 'Megatron',
form: 'Gun',
team: 'Decepticon'
},
{
name: 'Bumblebee',
form: 'VW Beetle',
team: 'Autobot'
},
{
name: 'Soundwave',
form: 'Walkman',
team: 'Decepticon'
}
];
那么,問題來了,如果想得到一個包含所有變形(form)的列表該怎么做呢? Array.map() 讓一切變得簡單。它的基本使用語法是這樣的:
Array.prototype.map(callback(item));
當然,還有種更復雜點的語法場景,只不過不常用到:
Array.prototype.map(callback(item[, index], array])[, thisArg]);
callback 會遍歷數組的每個元素,在其中返回的每一個數值將會組成新數組。 callback 有多種書寫方式:
命名函數:
functiongetForm(transformer){
return transformer.form;
}
var robotsInDisguise = transformers.map(getForm);
/** robosInDisguise === ['Freightliner Truck', 'Gun', 'VW Beetle', 'Walkman'] */
匿名函數:
robotsInDisguise = transformers.map(function(transformer){
return transformer.form;
});
箭頭函數:
robotsInDisguise = transformers.map(transformer => transformer.form);
ES2015的箭頭函數和 Array.map() 搭配使用簡直不能更爽了!
Array.filter()
語法:
Array.prototype.filter(callback(item));
callback 將數組元素當參數傳入,并返回一個布爾值。當返回值為真時,該元素被加入新數組中,反之則被過濾掉。
現在我們把這些變形金剛過濾出 汽車人 (Autobots)
functionisAutobot(transformer){
return transformer.team === ‘Autobot’;
}
var autobots = transformers.filter(isAutobot);
/**
autobots == [
{
name: 'Optimus Prime',
form: 'Freightliner Truck',
team: 'Autobot'
},
{
name: 'Bumblebee',
form: 'VW Beetle',
team: 'Autobot'
}
]
*/
Array.reduce()
Array.reduce() 是通過遍歷每個數組元素對其做運算,因此,也是三個API之間最富有技巧的,其使用語法也略顯復雜:
Array.prototype.reduce(callback(previousValue, currentValue[, index], array]), initialValue)
謹記一條:我們是將數組元素通過遍歷減少到一個值。比如現在有一組 可組合變形金剛 (譯者注:我也不知道什么鬼,該怎么翻譯,原詞:Construction Transformers),它們能夠組合成更大的變形金剛,我們可以通過代碼來做出這樣的組合:
var constructicons = [
{
name: 'Scrapper',
form: 'Freightliner Truck',
team: 'Decepticon',
bodyPart: 'rightLeg'
},
{
name: 'Hook',
form: 'Mobile Crane',
team: 'Decepticon',
bodyPart: 'upperTorso'
},
{
name: 'Bonecrusher',
form: 'Bulldozer',
team: 'Decepticon',
bodyPart: 'leftArm'
},
{
name: 'Scavenger',
form: 'Excavator',
team: 'Decepticon',
bodyPart: 'rightArm'
},
{
name: 'Mixmaster',
form: 'Concrete Mixer',
team: 'Decepticon',
bodyPart: 'leftLeg'
},
{
name: 'Long Haul',
form: 'Dump Truck',
team: 'Decepticon',
bodyPart: 'lowerTorso'
}
];
Reduce的 callback 需要至少兩個參數。第一個是從上次遍歷中返回的一個值,第二個是當前數組遍歷到的一個值,返回值又將當做第一個參數被傳入到下一次遍歷。
functionassemble(combiner, transformer){
//每次遍歷都會將當前的變形金剛(transformer)的名字加入到組合器(combiner)的form中去。
combiner.form[transformer.bodyPart] = transformer.name;
return combiner;
}
這樣,我們可以在調用reduce的時候,將 assemble 當做第一個參數傳入,第二個參數是用來初次調用時的初始數據。接下來的例子便是我們提供一個僅僅有名字(name)和派別(team)的變形金剛,通過reduce中的 assemble 我們來組合成一個強大的變形金剛吧!

var devastator = constructicons.reduce(assemble, {
name: ‘Devastator’,
team: ‘Decepticon’,
form: {}
});
/*
devastator == {
name: ‘Devastator’,
team: ‘Decepticon’,
form: {
leftArm: "Bonecrusher"
leftLeg: "Mixmaster"
lowerTorso: "Long Haul"
rightArm: "Scavenger"
rightLeg: "Scrapper"
upperTorso: "Hook"
}
}
*/
這些三個基本API一旦組合起來使用,也是很強大的。
來自:http://zerosoul.github.io/2016/12/06/array-filter-map-reduce-in-js/
