10 個超級實用的 reduce 使用技巧
reduce 函數(shù)可以根據(jù)需要進行累加、過濾、分組、映射等操作,是一個非常強大的數(shù)組方法。在數(shù)據(jù)處理時使用的非常頻繁,很多復(fù)雜的邏輯如果用reduce去處理,都非常的簡潔,在實際的開發(fā)工作過程中,積累了一些常見又超級好用的 reduce 技巧的代碼片段,篩選了如下 10 個,以供大家參考
reduce 介紹
reduce 是數(shù)組的方法,可以對數(shù)組中的每個元素依次執(zhí)行一個回調(diào)函數(shù),從左到右依次累積計算出一個最終的值。其語法為:
arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])
其中,callback 是每個元素執(zhí)行的回調(diào)函數(shù),其包含 4 個參數(shù):
-
accumulator:累積器,即上一次回調(diào)函數(shù)執(zhí)行的返回值。 -
currentValue:當前元素的值。 -
index:當前元素的下標。 -
array:原始數(shù)組。
initialValue 是可選的,表示累積器的初始值。
reduce 函數(shù)的執(zhí)行過程如下:
-
如果沒有提供
initialValue,則將數(shù)組的第一個元素作為累積器的初始值,否則將initialValue作為累積器的初始值。 - 從數(shù)組的第二個元素開始,依次對數(shù)組中的每個元素執(zhí)行回調(diào)函數(shù)。
- 回調(diào)函數(shù)的返回值作為下一次回調(diào)函數(shù)執(zhí)行時的累積器的值。
-
對數(shù)組中的每個元素執(zhí)行完回調(diào)函數(shù)后,
reduce函數(shù)返回最后一次回調(diào)函數(shù)的返回值,即最終的累積值。
計算數(shù)組中每個元素出現(xiàn)的次數(shù)
const?fruits?=?['apple',?'banana',?'apple',?'orange',?'banana',?'apple'];
const?count?=?fruits.reduce((accumulator,?currentValue)?=>?{
??accumulator[currentValue]?=?(accumulator[currentValue]?||?0)?+?1;
??return?accumulator;
},?{});
console.log(count);?//?Output:?{?apple:?3,?banana:?2,?orange:?1?}
拍平嵌套數(shù)組
const?nestedArray?=?[[1,?2],?[3,?4],?[5,?6]];
const?flattenedArray?=?nestedArray.reduce((accumulator,?currentValue)?=>?accumulator.concat(currentValue),?[]);
console.log(flattenedArray);?//?Output:?[1,?2,?3,?4,?5,?6]
按條件分組
const?people?=?[
??{?name:?'Alice',?age:?25?},
??{?name:?'Bob',?age:?30?},
??{?name:?'Charlie',?age:?35?},
??{?name:?'David',?age:?25?},
??{?name:?'Emily',?age:?30?}
];
const?groupedPeople?=?people.reduce((accumulator,?currentValue)?=>?{
??const?key?=?currentValue.age;
??if?(!accumulator[key])?{
????accumulator[key]?=?[];
??}
??accumulator[key].push(currentValue);
??return?accumulator;
},?{});
console.log(groupedPeople);
//?Output:?{
//???25:?[{?name:?'Alice',?age:?25?},?{?name:?'David',?age:?25?}],
//???30:?[{?name:?'Bob',?age:?30?},?{?name:?'Emily',?age:?30?}],
//???35:?[{?name:?'Charlie',?age:?35?}]
//?}
將多個數(shù)組合并為一個對象
const?keys?=?['name',?'age',?'gender'];
const?values?=?['Alice',?25,?'female'];
const?person?=?keys.reduce((accumulator,?currentValue,?index)?=>?{
????accumulator[currentValue]?=?values[index];
????return?accumulator;
??},?{});
console.log(person);?//?Output:?{?name:?'Alice',?age:?25,?gender:?'female'?}
將字符串轉(zhuǎn)換為對象
const?str?=?'key1=value1&key2=value2&key3=value3';
const?obj?=?str.split('&').reduce((accumulator,?currentValue)?=>?{
??const?[key,?value]?=?currentValue.split('=');
??accumulator[key]?=?value;
??return?accumulator;
},?{});
console.log(obj);?
//?Output:?{?key1:?'value1',?key2:?'value2',?key3:?'value3'?}
將對象轉(zhuǎn)換為查詢字符串
const?params?=?{?foo:?"bar",?baz:?42?};
const?queryString?=?Object.entries(params).reduce((acc,?[key,?value])?=>?{
??return?`${acc}${key}=${value}&`;
},?"?").slice(0,?-1);
console.log(queryString);?//?"?foo=bar&baz=42"
打印斐波那契數(shù)列
const?fibonacci?=?n?=>?{
??return?[...Array(n)].reduce((accumulator,?currentValue,?index)?=>?{
????if?(index?<?2)?{
??????accumulator.push(index);
????}?else?{
??????accumulator.push(accumulator[index?-?1]?+?accumulator[index?-?2]);
????}
????return?accumulator;
??},?[]);
};
console.log(fibonacci(10));?//?Output:?[0,?1,?1,?2,?3,?5,?8,?13,?21,?34]
檢查字符串是否是回文字符串
const?str?=?'racecar';
const?isPalindrome?=?str.split('').reduce((accumulator,?currentValue,?index,?array)?=>?{
??return?accumulator?&&?currentValue?===?array[array.length?-?index?-?1];
},?true);
console.log(isPalindrome);?//?Output:?true
檢查括號是否匹配
const?str?=?"(()()())";
const?balanced?=?str.split("").reduce((acc,?cur)?=>?{
??if?(cur?===?"(")?{
????acc++;
??}?else?if?(cur?===?")")?{
????acc--;
??}
??return?acc;
},?0)?===?0;
console.log(balanced);?//?true
遞歸獲取對象屬性
const?user?=?{
??info:?{
????name:?"Jason",
????address:?{?home:?"Shaanxi",?company:?"Xian"?},
??},
};
function?get(config,?path,?defaultVal)?{
??return?path.split('.').reduce((config,?name)?=>?config[name],?config)?||?defaultVal;
??return?fallback;
}
get(user,?"info.name");?//?Jason
get(user,?"info.address.home");?//?Shaanxi
get(user,?"info.address.company");?//?Xian
get(user,?"info.address.abc",?"default");?//?default
手寫 reduce
可以通過手寫一個簡單的 reduce 函數(shù)來更好地理解它的實現(xiàn)原理:
function?myReduce(arr,?callback,?initialValue)?{
??let?accumulator?=?initialValue?===?undefined???arr[0]?:?initialValue;
??for?(let?i?=?initialValue?===?undefined???1?:?0;?i?<?arr.length;?i++)?{
????accumulator?=?callback(accumulator,?arr[i],?i,?arr);
??}
??return?accumulator;
}
上面的代碼中,myReduce 函數(shù)接受 3 個參數(shù):要執(zhí)行 reduce 操作的數(shù)組 arr、回調(diào)函數(shù) callback 和累積器的初始值 initialValue。如果沒有提供初始值,則將數(shù)組的第一個元素作為累積器的初始值。
接下來,在循環(huán)中,如果有 initialValue,則從第一個元素開始遍歷 callback,此時 callabck 的第二個參數(shù)是從數(shù)組的第一項開始的;如果沒有 initialValue,則從第二個元素開始遍歷 callback,此時 callback 的第二個參數(shù)是從數(shù)組的第二項開始的從數(shù)組的第二個元素開始,依次對數(shù)組中的每個元素執(zhí)行回調(diào)函數(shù),并將返回值作為下一次回調(diào)函數(shù)執(zhí)行時的累積器的值。
最后,myReduce 函數(shù)返回最后一次回調(diào)函數(shù)的返回值,即最終的累積值。
這個簡易的 reduce 函數(shù)并沒有考慮很多邊界情況和復(fù)雜的應(yīng)用場景,但是可以幫助我們更好地理解 reduce 函數(shù)的實現(xiàn)原理。
關(guān)于本文
作者:shichuanhttps://juejin.cn/post/7224043114360225847最后
最后不要忘了點贊呦!
