程式碼寫得好,Reduce 方法少不了

前端小智發表於2022-05-06
作者:Ramgen
譯者:前端小智
來源:dev
有夢想,有乾貨,微信搜尋 【大遷世界】 關注這個在凌晨還在刷碗的刷碗智。
本文 GitHub https://github.com/qq449245884/xiaozhi 已收錄,有一線大廠面試完整考點、資料以及我的系列文章。

陣列中的 reduce 猶如一隻魔法棒,通過它可以做一些黑科技一樣的事情。語法如下:

reduce(callback(accumulator, currentValue[, index, array])[,initialValue])

reduce 接受兩個引數,回撥函式和初識值,初始值是可選的。回撥函式接受4個引數:積累值、當前值、當前下標、當前陣列。

如果 reduce的引數只有一個,那麼積累值一開始是陣列中第一個值,如果reduce的引數有兩個,那麼積累值一開始是出入的 initialValue 初始值。然後在每一次迭代時,返回的值作為下一次迭代的 accumulator 積累值。

今天的這些例子的大多數可能不是問題的理想解決方案,主要的目的是想說介紹如何使用reduce來解決問題。

求和和乘法

// 求和
[3, 5, 4, 3, 6, 2, 3, 4].reduce((a, i) => a + i);
// 30

// 有初始化值
[3, 5, 4, 3, 6, 2, 3, 4].reduce((a, i) => a + i, 5 );
// 35

// 如果看不懂第一個的程式碼,那麼下面的程式碼與它等價
[3, 5, 4, 3, 6, 2, 3, 4].reduce(function(a, i){return (a + i)}, 0 );

// 乘法
[3, 5, 4, 3, 6, 2, 3, 4].reduce((a, i) => a * i);

查詢陣列中的最大值

如果要使用 reduce 查詢陣列中的最大值,可以這麼做:

[3, 5, 4, 3, 6, 2, 3, 4].reduce((a, i) => Math.max(a, i), -Infinity);

上面,在每一次迭代中,我們返回累加器和當前項之間的最大值,最後我們得到整個陣列的最大值。

如果你真想在陣列中找到最大值,不要有上面這個,用下面這個更簡潔:

Math.max(...[3, 5, 4, 3, 6, 2, 3, 4]);

連線不均勻陣列

let data = [
  ["The","red", "horse"],
  ["Plane","over","the","ocean"],
  ["Chocolate","ice","cream","is","awesome"], 
  ["this","is","a","long","sentence"]
]
let dataConcat = data.map(item=>item.reduce((a,i)=>`${a} ${i}`))

// 結果
['The red horse', 
'Plane over the ocean', 
'Chocolate ice cream is awesome', 
'this is a long sentence']

在這裡我們使用 map 來遍歷陣列中的每一項,我們對所有的陣列進行還原,並將陣列還原成一個字串。

移除陣列中的重複項

let dupes = [1,2,3,'a','a','f',3,4,2,'d','d']
let withOutDupes = dupes.reduce((noDupes, curVal) => {
  if (noDupes.indexOf(curVal) === -1) { noDupes.push(curVal) }
  return noDupes
}, [])

檢查當前值是否在累加器陣列上存在,如果沒有則返回-1,然後新增它。

當然可以用 Set 的方式來快速刪除重複值,有興趣的可以自己去谷歌一下。

驗證括號

[..."(())()(()())"].reduce((a,i)=> i==='('?a+1:a-1,0);
// 0

[..."((())()(()())"].reduce((a,i)=> i==='('?a+1:a-1,0);
// 1

[..."(())()(()()))"].reduce((a,i)=> i==='('?a+1:a-1,0);
// -1

這是一個很酷的專案,之前在力扣中有刷到。

按屬性分組

let obj = [
  {name: 'Alice', job: 'Data Analyst', country: 'AU'},
  {name: 'Bob', job: 'Pilot', country: 'US'},
  {name: 'Lewis', job: 'Pilot', country: 'US'},
  {name: 'Karen', job: 'Software Eng', country: 'CA'},
  {name: 'Jona', job: 'Painter', country: 'CA'},
  {name: 'Jeremy', job: 'Artist', country: 'SP'},
]
let ppl = obj.reduce((group, curP) => {
  let newkey = curP['country']
  if(!group[newkey]){
    group[newkey]=[]
  }
  group[newkey].push(curP)
  return group
}, [])

這裡,我們根據 country 對第一個物件陣列進行分組,在每次迭代中,我們檢查鍵是否存在,如果不存在,我們建立一個陣列,然後將當前的物件新增到該陣列中,並返回組陣列。

你可以用它做一個函式,用一個指定的鍵來分組物件。

扁平陣列

let flattened = [[3, 4, 5], [2, 5, 3], [4, 5, 6]].reduce(
  (singleArr, nextArray) => singleArr.concat(nextArray), [])

// 結果:[3, 4, 5, 2, 5, 3, 4, 5, 6]

這只是一層,如果有多層,可以用遞迴函式來解決,但我不太喜歡在 JS 上做遞迴的東西?。

一個預定的方法是使用.flat方法,它將做同樣的事情

[ [3, 4, 5],
  [2, 5, 3],
  [4, 5, 6]
].flat();

只有冪的正數

[-3, 4, 7, 2, 4].reduce((acc, cur) => {
  if (cur> 0) {
    let R = cur**2;
    acc.push(R);
  }
  return acc;
}, []);

// 結果
[16, 49, 4, 144]

反轉字串

const reverseStr = str=>[...str].reduce((a,v)=>v+a)

這個方法適用於任何物件,不僅適用於字串。呼叫reverseStr("Hola"),輸出的結果是aloH

二進位制轉十進位制

const bin2dec = str=>[...String(str)].reduce((acc,cur)=>+cur+acc*2,0)

// 等價於

const bin2dec = (str) => {
  return [...String(str)].reduce((acc,cur)=>{
    return +cur+acc*2
  },0)
}

為了說明這一點,讓我們看一個例子:(10111)->1+(1+(1+(0+(1+0*2)*2)*2)*2)*2

~完,我是刷碗智,勵志等退休後,要回家擺地攤的人,我們下期見!


程式碼部署後可能存在的BUG沒法實時知道,事後為了解決這些BUG,花了大量的時間進行log 除錯,這邊順便給大家推薦一個好用的BUG監控工具 Fundebug

原文:https://dev.to/ramgendepy/lea...

交流

有夢想,有乾貨,微信搜尋 【大遷世界】 關注這個在凌晨還在刷碗的刷碗智。

本文 GitHub https://github.com/qq44924588... 已收錄,有一線大廠面試完整考點、資料以及我的系列文章。

相關文章