前言
關於數組的遍歷方法,我們使用最多的應該就是forEach和map了,一些人可能知道這兩個方法除去性能差別,最大的不同就是返回值還是原數組修改的問題,但是對更多的數組方法可能並不是很瞭解,fliter和some, every等方法這裏就不講了,他們的使用方式都比較好理解,這篇文章主要講講最麻煩的reduce。
累加
先來看看最簡單的用法,也是很多實例中使用的累加器手法:
> let a =[1,2,3]
undefined
> let b = a.reduce((a,b)=>a+b)
undefined
> b
6
我們拿這個例子簡單分析一下使用方法。
reduce接收兩個參數,一個是函數參數,一個是初始值,其中函數參數接收四個參數,後兩個和map的後兩個一樣是索引和數組,前兩個分別爲處理後的返回值和下一個要處理的值。
對於上面的例子,我們並不存在初始值,所以初始值默認爲數組的第一個值,即爲1,則第一次調用時a爲1,b爲2,返回後第二次a即爲1+2=3,這是b取到最後的3,則a爲3+3=6,最後返回的值即循環結束後a的值。
上面的例子也可以寫爲:
> let a =[1,2,3]
undefined
> let b = a.reduce((a,b)=>a+b,0)
undefined
> b
6
下面說幾個應用,上面這個例子已經是一類了,即作爲累加或累乘。
加權求和
> a
[
{ category: 'math', score: 90, weight: 0.5 },
{ category: 'language', score: 80, weight: 0.5 },
{ category: 'music', score: 40, weight: 0.2 }
]
> a.reduce((t,v)=>t+v.score*v.weight,0)
93
數組求差
在A數組中找到B數組中不存在的值是一項挺常見的操作,使用reduce可以比較簡單的實現:
a1.reduce(
(t,v)=>{
!a2.includes(v)&&t.push(v);
return t
},[]
)
當然使用逗號操作符可以更加簡單的完成:
a1.reduce((t,v)=>(!a2.includes(v)&&t.push(v), t), [])
防止大家對逗號操作不瞭解,舉個簡單的例子:
> (console.log(2),2)
2
2
數組扁平化
數組扁平化是挺常見的面試題:
function Flat(a){
return a.reduce((t,v)=>
t.concat(Array.isArray(v)?Flat(v):v)
,[])
}
數組去重
之前用Python的時候做去重很簡單,用集合包裹一下然後轉化爲數組即可,JS之後不屑於這麼操作了。
a.reduce((t,v)=>
(!t.includes(v)?t.push(v):null ,t),[]
)
數組拆解組合
數組拆解組合在有些地方是挺有用的:
function unZip(arr = []) {
return arr.reduce(
(t, v) => (v.forEach((v, i) => t[i].push(v)), t),
Array.from({ length: Math.max(...arr.map(v => v.length)) }).map(v => [])
);
}
統計數出現個數
還是用逗號操作符簡化:
> a.reduce((t,v)=>(t[v]=(t[v]||0)+1, t),{})
總結
數組基本上可以說是平常開發用的很多的數據結構,reduce方法其實是可以覆蓋大部分其他方法的,當然它的性能也不差,平時可以使用一手。