溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Javascript數(shù)組方法reduce怎么用

發(fā)布時(shí)間:2021-08-18 14:37:01 來(lái)源:億速云 閱讀:108 作者:小新 欄目:web開(kāi)發(fā)

這篇文章主要為大家展示了“Javascript數(shù)組方法reduce怎么用”,內(nèi)容簡(jiǎn)而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“Javascript數(shù)組方法reduce怎么用”這篇文章吧。

語(yǔ)法

array.reduce(function(accumulator, arrayElement, currentIndex, arr), initialValue)

若傳入初始值,accumulator首次迭代就是初始值,否則就是數(shù)組的第一個(gè)元素;后續(xù)迭代中將是上一次迭代函數(shù)返回的結(jié)果。所以,假如數(shù)組的長(zhǎng)度為n,如果傳入初始值,迭代次數(shù)為n;否則為n-1。

比如實(shí)現(xiàn)數(shù)組 arr = [1,2,3,4] 求數(shù)組的和

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

實(shí)際上reduce還有很多重要的用法,這是因?yàn)槔奂悠鞯闹悼梢圆槐貫楹?jiǎn)單類(lèi)型(如數(shù)字或字符串),它也可以是結(jié)構(gòu)化類(lèi)型(如數(shù)組或?qū)ο螅?,這使得我們可以用它做一些其他有用的事情,比如:

  • 將數(shù)組轉(zhuǎn)換為對(duì)象

  • 展開(kāi)更大的數(shù)組

  • 在一次遍歷中進(jìn)行兩次計(jì)算

  • 將映射和過(guò)濾函數(shù)組合

  • 按順序運(yùn)行異步函數(shù)

將數(shù)組轉(zhuǎn)化為對(duì)象

在實(shí)際業(yè)務(wù)開(kāi)發(fā)中,你可能遇到過(guò)這樣的情況,后臺(tái)接口返回的數(shù)組類(lèi)型,你需要將它轉(zhuǎn)化為一個(gè)根據(jù)id值作為key,將數(shù)組每項(xiàng)作為value的對(duì)象進(jìn)行查找。

例如:

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: ''
 }
];

如果你用過(guò)lodash這個(gè)庫(kù),使用_.keyBy這個(gè)方法就能進(jìn)行轉(zhuǎn)換,但用reduce也能實(shí)現(xiàn)這樣的需求。

function keyByUsernameReducer(acc, person) {
 return {...acc, [person.id]: person};
}
const userObj = peopleArr.reduce(keyByUsernameReducer, {});
console.log(userObj);

將小數(shù)組展開(kāi)成大數(shù)組

試想這樣一個(gè)場(chǎng)景,我們將一堆純文本行讀入數(shù)組中,我們想用逗號(hào)分隔每一行,生成一個(gè)更大的數(shù)組名單。

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"
// ]

我們從長(zhǎng)度為5的數(shù)組開(kāi)始,最后得到一個(gè)長(zhǎng)度為16的數(shù)組。

另一種常見(jiàn)增加數(shù)組的情況是flatMap,有時(shí)候我們用map方法需要將二級(jí)數(shù)組展開(kāi),這時(shí)可以用reduce實(shí)現(xiàn)扁平化

例如:

Array.prototype.flatMap = function(f) {
 const reducer = (acc, item) => acc.concat(f(item));
 return this.reduce(reducer, []);
}

const arr = ["今天天氣不錯(cuò)", "", "早上好"]

const arr1 = arr.map(s => s.split(""))
// [["今", "天", "天", "氣", "不", "錯(cuò)"],[""],["早", "上", "好"]]

const arr2 = arr.flatMap(s => s.split(''));
// ["今", "天", "天", "氣", "不", "錯(cuò)", "", "早", "上", "好"]

在一次遍歷中進(jìn)行兩次計(jì)算

有時(shí)我們需要對(duì)數(shù)組進(jìn)行兩次計(jì)算。例如,我們可能想要計(jì)算數(shù)字列表的最大值和最小值。我們可以通過(guò)兩次通過(guò)這樣做:

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}

這需要遍歷我們的數(shù)組兩次。但是,有時(shí)我們可能不想這樣做。因?yàn)?reduce()讓我們返回我們想要的任何類(lèi)型,我們不必返回?cái)?shù)字。我們可以將兩個(gè)值編碼到一個(gè)對(duì)象中。然后我們可以在每次迭代時(shí)進(jìn)行兩次計(jì)算,并且只遍歷數(shù)組一次:

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}

將映射和過(guò)濾合并為一個(gè)過(guò)程

還是先前那個(gè)用戶列表,我們希望找到?jīng)]有電子郵件地址的人的用戶名,返回它們用戶名用逗號(hào)拼接的字符串。一種方法是使用兩個(gè)單獨(dú)的操作:

  • 獲取過(guò)濾無(wú)電子郵件后的條目

  • 獲取用戶名并拼接

將它們放在一起可能看起來(lái)像這樣:

function notEmptyEmail(x) {
 return !!x.email
}

function notEmptyEmailUsername(a, b) {
 return a ? `${a},${b.username}` : b.username
}

const userWithEmail = userList.filter(notEmptyEmail);
const userWithEmailFormatStr = userWithEmail.reduce(notEmptyEmailUsername, '');

console.log(userWithEmailFormatStr);
// 'john,jerry'

現(xiàn)在,這段代碼是完全可讀的,對(duì)于小的樣本數(shù)據(jù)不會(huì)有性能問(wèn)題,但是如果我們有一個(gè)龐大的數(shù)組呢?如果我們修改我們的reducer回調(diào),那么我們可以一次完成所有事情:

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'

在這個(gè)版本中,我們只遍歷一次數(shù)組,一般建議使用filter和map的組合,除非發(fā)現(xiàn)性能問(wèn)題,才推薦使用reduce去做優(yōu)化。

按順序運(yùn)行異步函數(shù)

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

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

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函數(shù)返回一個(gè) Promise 對(duì)象,可以使用then方法添加回調(diào)函數(shù)。當(dāng)函數(shù)執(zhí)行的時(shí)候,一旦遇到await就會(huì)先返回,等到異步操作完成,再接著執(zhí)行函數(shù)體內(nèi)后面的語(yǔ)句。

請(qǐng)注意,在此我們傳遞Promise作為初始值Promise.resolve(),我們的第一個(gè)API調(diào)用將立即運(yùn)行。

下面是不使用async語(yǔ)法糖的版本

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: [ … ]}

以上是“Javascript數(shù)組方法reduce怎么用”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI