JS數組的reduce()方法還能這麼用?

Array.prototype.reduce()數組

reduce() 方法對數組中的每一個元素執行一個reducer函數(升序執行),將其結果彙總爲單個返回值。app

const arr1 = [1, 2, 3, 4];
const reducer = (accumulator, currentValue) => accumulator + currentValue;
// 1 + 2 + 3 + 4
console.log(arr1.reduce(reducer));
// output: 10

// 5 + 1 + 2 + 3 + 4
console.log(arr1.reduce(reducer, 5));
// output: 15

1、語法

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

1.參數
callback
執行數組中每一個值(若是沒有提供 initialValue,則第一個值除外)的函數,包含四個參數:函數

accumulator
累計器累計回調的返回值; 它是上一次調用回調時返回的累積值,或initialValue(見於下方)。this

currentValue
數組中正在處理的元素。prototype

index:可選
數組中正在處理的當前元素的索引。 若是提供了 initialValue,則起始索引號爲0,不然從索引1起始。code

array:可選
調用reduce()的數組。對象

initialValue:可選
做爲第一次調用 callback 函數時的第一個參數的值。 若是沒有提供初始值,則將使用數組中的第一個元素。 在沒有初始值的空數組上調用 reduce 將報錯。索引

2.返回值
函數累計處理的結果。ip

2、描述

回調函數第一次執行時,accumulator 和 currentValue 的取值有兩種狀況:
若是調用reduce()時提供了initialValue,accumulator取值爲initialValue,currentValue取數組中的第一個值;
若是沒有提供 initialValue,那麼accumulator取數組中的第一個值,currentValue取數組中的第二個值。input

注意:若是沒有提供initialValue,reduce 會從索引1的地方開始執行 callback 方法,跳過第一個索引。若是提供initialValue,從索引0開始。

3、舉例

1.求出數組裏全部值的和

let sum = [ 0, 1, 2, 3 ].reduce((acc, cur) => acc + cur, 0);
console.log(sum); // 6

2.累加對象數組裏的值

let total = [{x: 1}, {x:2}, {x:3}].reduce((acc, cur) => acc + cur.x, 0);
console.log(total); // 6

3.將二維數組轉化爲一維

let flattened = [[0, 1], [2, 3], [4, 5]].reduce((acc, cur) => acc.concat(cur), []);
console.log(flattened); // [0, 1, 2, 3, 4, 5]

4.計算數組中每一個元素出現的次數

let names = ['lxcan', 'splendid', 'ican', 'volcano', 'lxcan'];
let countedNames = names.reduce((allNames, name) => {
    if (name in allNames) {
        allNames[name]++;
    } else {
        allNames[name] = 1;
    }
    return allNames;
}, {});
console.log(countedNames);
// { 'lxcan': 2, 'splendid': 1, 'ican': 1, 'volcano': 1 }

5.按屬性對object分類

let peoples = [
    { name: 'lxcan', age: 20 },
    { name: 'ican', age: 20 },
    { name: 'splendid', age: 18 }
];

function groupBy(arr, property) {
    return arr.reduce((acc, obj) => {
        let key = obj[property];
        if (!acc[key]) {
            acc[key] = [];
        }
        acc[key].push(obj);
        return acc;
    }, {});
}

let groupedPeople = groupBy(peoples, 'age');
console.log(groupedPeople);
// {
//   18: [{ name: 'splendid', age: 18 }]
//   20: [
//     { name: 'lxcan', age: 20 },
//     { name: 'ican', age: 20 }
//   ],
// }

6.使用擴展運算符和initialValue綁定包含在對象數組中的數組

// friends - 對象數組
let friends = [{
    name: 'Anna',
    books: ['Bible', 'Harry Potter'],
    age: 21
}, {
    name: 'Bob',
    books: ['War and peace', 'Romeo and Juliet'],
    age: 26
}, {
    name: 'Alice',
    books: ['The Shining'],
    age: 18
}];

// allbooks - 包含全部朋友的書 + initialValue 中的附加列表
let allBooks = friends.reduce(function(prev, curr) {
    return [...prev, ...curr.books];
}, ['Alphabet']);
console.log(allBooks);
// ['Alphabet', 'Bible', 'Harry Potter', 'War and peace', 'Romeo and Juliet', 'The Shining']

7.功能型函數封裝

const double = x => 2 * x;
const triple = x => 3 * x;
const quadruple = x => 4 * x;

// 對功能函數進行封裝
const pipe = (...functions) => {
    return input => functions.reduce((acc, fn) => fn(acc), input)
};

// 用於特定值組合乘法的複合函數
const multiply6 = pipe(double, triple);
const multiply9 = pipe(triple, triple);
const multiply16 = pipe(quadruple, quadruple);
const multiply24 = pipe(double, triple, quadruple);

// 使用
multiply6(6); // 36
multiply9(9); // 81
multiply16(16); // 256
multiply24(10); // 240

8.使用 reduce 實現map

if (!Array.prototype.mapByReduce) {
    Array.prototype.mapByReduce = function(callback, thisArg) {
        return this.reduce(function(mappedArray, currentValue, index, array) {
            mappedArray[index] = callback.call(thisArg, currentValue, index, array);
            return mappedArray;
        }, []);
    };
}

let arr = [1, 2, 3].mapByReduce((value, index, array) => value + index + array.length);
console.log(arr); // [4, 6, 8]
相關文章
相關標籤/搜索