成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Javascript中數(shù)組方法reduce的妙用之處

yiliang / 1914人閱讀

摘要:數(shù)組方法中,相比等常用的迭代方法,常常被我們所忽略,今天一起來探究一下在我們實(shí)戰(zhàn)開發(fā)當(dāng)中,能有哪些妙用之處,下面從語法開始介紹。按順序運(yùn)行異步函數(shù)我們可以做的另一件事是按順序運(yùn)行而不是并行。函數(shù)返回一個(gè)對象,可以使用方法添加回調(diào)函數(shù)。

Javascript數(shù)組方法中,相比map、filterforEach等常用的迭代方法,reduce常常被我們所忽略,今天一起來探究一下reduce在我們實(shí)戰(zhàn)開發(fā)當(dāng)中,能有哪些妙用之處,下面從reduce語法開始介紹。

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

若傳入初始值,accumulator首次迭代就是初始值,否則就是數(shù)組的第一個(gè)元素;后續(xù)迭代中將是上一次迭代函數(shù)返回的結(jié)果。所以,假如數(shù)組的長度為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)槔奂悠鞯闹悼梢圆槐貫楹唵晤愋停ㄈ鐢?shù)字或字符串),它也可以是結(jié)構(gòu)化類型(如數(shù)組或?qū)ο螅?,這使得我們可以用它做一些其他有用的事情,比如:

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

展開更大的數(shù)組

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

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

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

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

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

例如:

const userList = [
  {
    id: 1,
    username: "john",
    sex: 1,
    email: "[email protected]"
  },
  {
    id: 2,
    username: "jerry",
    sex: 1,
    email: "[email protected]"
  },
  {
    id: 3,
    username: "nancy",
    sex: 0,
    email: ""
  }
];

如果你用過lodash這個(gè)庫,使用_.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ù)組展開成大數(shù)組

試想這樣一個(gè)場景,我們將一堆純文本行讀入數(shù)組中,我們想用逗號分隔每一行,生成一個(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"
// ]

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

另一種常見增加數(shù)組的情況是flatMap,有時(shí)候我們用map方法需要將二級數(shù)組展開,這時(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í)我們需要對數(shù)組進(jìn)行兩次計(jì)算。例如,我們可能想要計(jì)算數(shù)字列表的最大值和最小值。我們可以通過兩次通過這樣做:

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()讓我們返回我們想要的任何類型,我們不必返回?cái)?shù)字。我們可以將兩個(gè)值編碼到一個(gè)對象中。然后我們可以在每次迭代時(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}
將映射和過濾合并為一個(gè)過程

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

獲取過濾無電子郵件后的條目

獲取用戶名并拼接

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

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)在,這段代碼是完全可讀的,對于小的樣本數(shù)據(jù)不會有性能問題,但是如果我們有一個(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ù)組,一般建議使用filtermap的組合,除非發(fā)現(xiàn)性能問題,才推薦使用reduce去做優(yōu)化。

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

我們可以做的另一件事.reduce()是按順序運(yùn)行promises(而不是并行)。如果您對API請求有速率限制,或者您需要將每個(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 對象,可以使用then方法添加回調(diào)函數(shù)。當(dāng)函數(shù)執(zhí)行的時(shí)候,一旦遇到await就會先返回,等到異步操作完成,再接著執(zhí)行函數(shù)體內(nèi)后面的語句。

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

下面是不使用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:更多前端資訊、技術(shù)干貨,請關(guān)注公眾號「前端新視界

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/104519.html

相關(guān)文章

  • reduce妙用

    摘要:為數(shù)組的每一項(xiàng)為數(shù)組的下標(biāo)為原數(shù)組如果沒傳第一次為數(shù)組的第一項(xiàng),之后為的值。為從數(shù)組的第二項(xiàng)開始的每一項(xiàng)不受影響下劃線轉(zhuǎn)駝峰數(shù)組扁平化二維轉(zhuǎn)一維數(shù)組轉(zhuǎn)對象路由數(shù)組轉(zhuǎn)對象 reduce 數(shù)組的方法,有兩個(gè)參數(shù) 回調(diào)函數(shù)callback 和 initialValue回調(diào)有四個(gè)參數(shù) prev、next、index、arrinitialValue:可選參數(shù),作為callback第一次的prev...

    blastz 評論0 收藏0
  • 簡約強(qiáng)大數(shù)組操作組合

    摘要:一個(gè)歸并方法第一個(gè)參數(shù)是每一項(xiàng)上調(diào)用的函數(shù),該函數(shù)有四個(gè)參數(shù)累加回調(diào)返回值他是上一次調(diào)用時(shí)返回的累積值,或數(shù)組中正在處理的元素?cái)?shù)組中正在處理的當(dāng)前元素的索引。統(tǒng)計(jì)數(shù)組中重復(fù)出現(xiàn)項(xiàng)的個(gè)數(shù),用對象表示。 前言 在實(shí)際js開發(fā)中對數(shù)組操作頻率非常高,看過一些小伙伴的一些用法,挺有意思,在這里小記(不全)一下,備忘。 showImg(https://segmentfault.com/img/r...

    chenjiang3 評論0 收藏0
  • 全本 | iKcamp翻譯 | 《JavaScript 輕量級函數(shù)式編程》|《你不知道JS》姊妹篇

    摘要:本書主要探索函數(shù)式編程的核心思想。我們在中應(yīng)用的僅僅是一套基本的函數(shù)式編程概念的子集。我稱之為輕量級函數(shù)式編程。通常來說,關(guān)于函數(shù)式編程的書籍都熱衷于拓展閱讀者的知識面,并企圖覆蓋更多的知識點(diǎn)。,本書統(tǒng)稱為函數(shù)式編程者。 原文地址:Functional-Light-JS 原文作者:Kyle Simpson?。 禮ou-Dont-Know-JS》作者 譯者團(tuán)隊(duì)(排名不分先后)...

    paney129 評論0 收藏0
  • 數(shù)組reduce方法高級技巧

    摘要:我們在的第二個(gè)參數(shù)里面初始了回調(diào)函數(shù)第一個(gè)參數(shù)的類型和值,將字符串轉(zhuǎn)化為數(shù)組,那么迭代的結(jié)果將是一個(gè)對象,對象的每一項(xiàng)值就是字符串的字母。 因?yàn)橛胒or循環(huán)被老大鄙視之后,這幾天都在偷偷摸摸的研究數(shù)組的那幾個(gè)迭代方法。使用下來,感覺確實(shí)妙用無窮,仿佛自己的逼格在無形中變得高大了一點(diǎn)點(diǎn),哈哈,上一篇文章的簡單介紹確實(shí)有點(diǎn)糙,因此決定重新一些總結(jié)文章。 這篇文章就是專門總結(jié)reduce方法...

    yvonne 評論0 收藏0
  • 數(shù)組reduce方法高級技巧

    摘要:我們在的第二個(gè)參數(shù)里面初始了回調(diào)函數(shù)第一個(gè)參數(shù)的類型和值,將字符串轉(zhuǎn)化為數(shù)組,那么迭代的結(jié)果將是一個(gè)對象,對象的每一項(xiàng)值就是字符串的字母。 因?yàn)橛胒or循環(huán)被老大鄙視之后,這幾天都在偷偷摸摸的研究數(shù)組的那幾個(gè)迭代方法。使用下來,感覺確實(shí)妙用無窮,仿佛自己的逼格在無形中變得高大了一點(diǎn)點(diǎn),哈哈,上一篇文章的簡單介紹確實(shí)有點(diǎn)糙,因此決定重新一些總結(jié)文章。 這篇文章就是專門總結(jié)reduce方法...

    mudiyouyou 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<