日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

JavaScript 中数组方法 reduce 的妙用之处

發布時間:2025/3/15 javascript 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JavaScript 中数组方法 reduce 的妙用之处 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Javascript數組方法中,相比map、filter、forEach等常用的迭代方法,reduce常常被我們所忽略,今天一起來探究一下reduce在我們實戰開發當中,能有哪些妙用之處,下面從reduce語法開始介紹。

語法

array.reduce(function(accumulator, arrayElement, currentIndex, arr), initialValue) 復制代碼

若傳入初始值,accumulator首次迭代就是初始值,否則就是數組的第一個元素;后續迭代中將是上一次迭代函數返回的結果。所以,假如數組的長度為n,如果傳入初始值,迭代次數為n;否則為n-1。

比如實現數組 arr = [1,2,3,4] 求數組的和

let arr = [1,2,3,4]; arr.reduce(function(pre,cur){return pre + cur}); // return 10 復制代碼

實際上reduce還有很多重要的用法,這是因為累加器的值可以不必為簡單類型(如數字或字符串),它也可以是結構化類型(如數組或對象),這使得我們可以用它做一些其他有用的事情,比如:

  • 將數組轉換為對象
  • 展開更大的數組
  • 在一次遍歷中進行兩次計算
  • 將映射和過濾函數組合
  • 按順序運行異步函數

將數組轉化為對象

在實際業務開發中,你可能遇到過這樣的情況,后臺接口返回的數組類型,你需要將它轉化為一個根據id值作為key,將數組每項作為value的對象進行查找。

例如:

const userList = [{id: 1,username: 'john',sex: 1,email: 'john@163.com'},{id: 2,username: 'jerry',sex: 1,email: 'jerry@163.com'},{id: 3,username: 'nancy',sex: 0,email: ''} ]; 復制代碼

如果你用過lodash這個庫,使用_.keyBy這個方法就能進行轉換,但用reduce也能實現這樣的需求。

function keyByUsernameReducer(acc, person) {return {...acc, [person.id]: person}; } const userObj = userList.reduce(keyByUsernameReducer, {}); console.log(userObj); // { // 1: { // id: 1, // username: 'john', // sex: 1, // email: 'john@163.com' // }, // 2: { // id: 2, // username: 'jerry', // sex: 1, // email: 'jerry@163.com' // }, // 3: { // id: 3, // username: 'nancy', // sex: 0, // email: '' // } // } 復制代碼

將小數組展開成大數組

試想這樣一個場景,我們將一堆純文本行讀入數組中,我們想用逗號分隔每一行,生成一個更大的數組名單。

const fileLines = ['Inspector Algar,Inspector Bardle,Mr. Barker,Inspector Barton','Inspector Baynes,Inspector Bradstreet,Inspector Sam Brown','Monsieur Dubugue,Birdy Edwards,Inspector Forbes,Inspector Forrester','Inspector Gregory,Inspector Tobias Gregson,Inspector Hill','Inspector Stanley Hopkins,Inspector Athelney Jones' ];function splitLineReducer(acc, line) {return acc.concat(line.split(/,/g)); } const investigators = fileLines.reduce(splitLineReducer, []); console.log(investigators); // [ // "Inspector Algar", // "Inspector Bardle", // "Mr. Barker", // "Inspector Barton", // "Inspector Baynes", // "Inspector Bradstreet", // "Inspector Sam Brown", // "Monsieur Dubugue", // "Birdy Edwards", // "Inspector Forbes", // "Inspector Forrester", // "Inspector Gregory", // "Inspector Tobias Gregson", // "Inspector Hill", // "Inspector Stanley Hopkins", // "Inspector Athelney Jones" // ] 復制代碼

我們從長度為5的數組開始,最后得到一個長度為16的數組。

另一種常見增加數組的情況是flatMap,有時候我們用map方法需要將二級數組展開,這時可以用reduce實現扁平化

例如:

Array.prototype.flatMap = function(f) {const reducer = (acc, item) => acc.concat(f(item));return this.reduce(reducer, []); }const arr = ["今天天氣不錯", "", "早上好"]const arr1 = arr.map(s => s.split("")) // [["今", "天", "天", "氣", "不", "錯"],[""],["早", "上", "好"]]const arr2 = arr.flatMap(s => s.split('')); // ["今", "天", "天", "氣", "不", "錯", "", "早", "上", "好"] 復制代碼

在一次遍歷中進行兩次計算

有時我們需要對數組進行兩次計算。例如,我們可能想要計算數字列表的最大值和最小值。我們可以通過兩次通過這樣做:

const readings = [0.3, 1.2, 3.4, 0.2, 3.2, 5.5, 0.4]; const maxReading = readings.reduce((x, y) => Math.max(x, y), Number.MIN_VALUE); const minReading = readings.reduce((x, y) => Math.min(x, y), Number.MAX_VALUE); console.log({minReading, maxReading}); // {minReading: 0.2, maxReading: 5.5} 復制代碼

這需要遍歷我們的數組兩次。但是,有時我們可能不想這樣做。因為.reduce()讓我們返回我們想要的任何類型,我們不必返回數字。我們可以將兩個值編碼到一個對象中。然后我們可以在每次迭代時進行兩次計算,并且只遍歷數組一次:

const readings = [0.3, 1.2, 3.4, 0.2, 3.2, 5.5, 0.4]; function minMaxReducer(acc, reading) {return {minReading: Math.min(acc.minReading, reading),maxReading: Math.max(acc.maxReading, reading),}; } const initMinMax = {minReading: Number.MAX_VALUE,maxReading: Number.MIN_VALUE, }; const minMax = readings.reduce(minMaxReducer, initMinMax); console.log(minMax); // {minReading: 0.2, maxReading: 5.5} 復制代碼

將映射和過濾合并為一個過程

還是先前那個用戶列表,我們希望找到沒有電子郵件地址的人的用戶名,返回它們用戶名用逗號拼接的字符串。一種方法是使用三個單獨的操作:

  • 獲取過濾無電子郵件后的用戶
  • 獲取用戶名列表
  • 拼接用戶名

將它們放在一起可能看起來像這樣:

function notEmptyEmail(x) {return !!x.email }function notEmptyEmailUsername(a, b) {return a ? `${a},${b}` : b }const userWithEmail = userList.filter(notEmptyEmail); const usernameWithEmail = userWithEmail.map((user=> user.username) const userWithEmailFormatStr = userWithEmail.reduce(notEmptyEmailUsername, '');console.log(userWithEmailFormatStr); // 'john,jerry' 復制代碼

現在,這段代碼是完全可讀的,對于小的樣本數據不會有性能問題,但是如果我們有一個龐大的數組呢?如果我們修改我們的reducer回調,那么我們可以一次完成所有事情:

function notEmptyEmail(x) {return !!x.email }function notEmptyEmailUsername(usernameAcc, person){return (notEmptyEmail(person))? (usernameAcc ? `${usernameAcc},${person.username}` : `${person.username}`) : usernameAcc; }const userWithEmailFormatStr = userList.reduce(notEmptyEmailUsername, '');console.log(userWithEmailFormatStr); // 'john,jerry' 復制代碼

在這個版本中,我們只遍歷一次數組,一般建議使用filter和map的組合,除非發現性能問題,才推薦使用reduce去做優化。

按順序運行異步函數

我們可以做的另一件事.reduce()是按順序運行promises(而不是并行)。如果您對API請求有速率限制,或者您需要將每個prmise的結果傳遞到下一個promise,reduce可以幫助到你。

舉一個例子,假設我們想要為userList數組中的每個人獲取消息。

function fetchMessages(username) {return fetch(`https://example.com/api/messages/${username}`).then(response => response.json()); }function getUsername(person) {return person.username; }async function chainedFetchMessages(p, username) {// In this function, p is a promise. We wait for it to finish,// then run fetchMessages().const obj = await p;const data = await fetchMessages(username);return { ...obj, [username]: data}; }const msgObj = userList.map(getUsername).reduce(chainedFetchMessages, Promise.resolve({})).then(console.log); // {glestrade: [ … ], mholmes: [ … ], iadler: [ … ]} 復制代碼

async函數返回一個 Promise 對象,可以使用then方法添加回調函數。當函數執行的時候,一旦遇到await就會先返回,等到異步操作完成,再接著執行函數體內后面的語句。

請注意,在此我們傳遞Promise作為初始值Promise.resolve(),我們的第一個API調用將立即運行。

下面是不使用async語法糖的版本

function fetchMessages(username) {return fetch(`https://example.com/api/messages/${username}`).then(response => response.json()); }function getUsername(person) {return person.username; }function chainedFetchMessages(p, username) {// In this function, p is a promise. We wait for it to finish,// then run fetchMessages().return p.then((obj)=>{return fetchMessages(username).then(data=>{return {...obj,[username]: data}})}) }const msgObj = peopleArr.map(getUsername).reduce(chainedFetchMessages, Promise.resolve({})).then(console.log); // {glestrade: [ … ], mholmes: [ … ], iadler: [ … ]} 復制代碼

PS:更多前端資訊、技術干貨,請關注公眾號「前端新視界

轉載于:https://juejin.im/post/5cfcaa7ae51d45109b01b161

總結

以上是生活随笔為你收集整理的JavaScript 中数组方法 reduce 的妙用之处的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 久久精品免费av | 天天综合网永久 | 91黄瓜视频 | 国产三级国产精品国产国在线观看 | 久久久国产成人 | 人妻无码中文字幕 | 91日韩视频 | 亚洲欧美精品suv | 无码人妻丰满熟妇区毛片蜜桃精品 | 免费欧美一区 | 国产成年网站 | 人妻一区二区三区免费 | 6680新视觉电影免费观看 | 午夜久久久久久久久久影院 | 日韩av一区二区在线 | 人与动物黄色片 | av国语| av黄色免费 | 国产卡一卡二卡三无线乱码新区 | 日本特级黄色 | 四虎精品 | 日韩第二页| 亚洲一本之道 | 国产一区自拍视频 | 俄罗斯av在线 | 强行侵犯视频在线观看 | 国模私拍一区二区三区 | 日韩三级麻豆 | 免费精品一区 | 国产欧美一区二区三区白浆喷水 | 操操插插| 欧美日韩午夜精品 | 亚洲va中文字幕 | 国产精品成人aaaaa网站 | 特级做a爰片毛片免费69 | 一本色道久久88综合无码 | 日韩中文字幕视频在线 | 国产女主播视频 | 免费啪视频在线观看 | 大尺度电影在线 | 国产精品第三页 | 午夜资源| 国产又黄又猛又粗 | 国产精品久久久久久影视 | 一本亚洲| 国产九色视频 | 亚洲AV无码阿娇国产精品 | 夜夜骑狠狠干 | 亚洲国产一区二区三区四区 | 无码精品人妻一区二区 | 精品人妻无码一区二区三区蜜桃一 | 开心激情站 | 日韩成人精品一区二区三区 | 亚洲精品合集 | 天天操天天做 | 日本精品视频在线播放 | 黑人三级视频 | 天堂а√在线中文在线新版 | 国产乱码一区二区 | 欧美日韩高清一区二区三区 | 国产午夜一区 | 香蕉视频官方网站 | 久久免费毛片 | 天天干少妇| 国产日韩视频在线 | 欧美性猛交bbbbb精品 | 在线观看的毛片 | 性活交片大全免费看 | 91九色国产ts另类人妖 | 热热色av| 一区二区三区免费在线视频 | 欧美日韩激情视频 | 欧美激情 在线 | 天堂√| 美女又爽又黄视频毛茸茸 | www.色亚洲 | 青青草视频免费 | 亚洲视频一区在线观看 | 女人被狂躁60分钟视频 | 亚洲精品喷潮一区二区三区 | 巨胸喷奶水www久久久免费动漫 | 婷婷超碰 | 国产精品美女在线观看 | 午夜免费一区 | 9.1成人看片 | 超碰黑人 | 波多野结衣中文字幕在线 | 午夜免费福利在线观看 | 国产精品999 | 无码丰满熟妇 | 国产一区二区在线免费 | 777理伦三级做爰 | 91久久精品夜夜躁日日躁欧美 | 欧美性大战久久久久久久 | 国产黄色片视频 | 狠狠躁日日躁夜夜躁 | 成人在线免费网站 | 青青草97国产精品免费观看 | 国产三级三级三级 |