一文看懂全能的reduce

前言

關於數組的遍歷方法,我們使用最多的應該就是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方法其實是可以覆蓋大部分其他方法的,當然它的性能也不差,平時可以使用一手。

發佈了386 篇原創文章 · 獲贊 411 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章