iT邦幫忙

2021 iThome 鐵人賽

DAY 14
0
Modern Web

我的JavaScript日常系列 第 14

JavaScript Day 14. 靈活運用 reduce()

前幾篇一個陰錯陽差發現了 reduce,不小心產生了好感(?),於是很興奮的說要之後再找時間介紹,寫完 forEach 後突然就決定不然就介紹一下 reduce 好了,顆顆。

不過說是介紹,事實是我才疏學淺,只能算是跟各位分享我的研究結果,如果各位有什麼其他的想法也可以再幫我補充補充,那麼我們就開始來討論一下 reduce 到底怎麼使用吧。

這邊先引用MDN對 reduce 的一句話解釋:

reduce() 方法將一個累加器及陣列中每項元素(由左至右)傳入回呼函式,將陣列化為單一值。

用自己的話來解釋上面這段則大概是,reduce 方法會針對陣列中的每一個元素,傳入指定的函數,並且是由左至右,最後再回傳一個累加的值。其實我在 map 方法的時候有大概的用範例解釋了一下 reduce 方法,感覺 reduce 在搭配 map 也是十分的好用。

以下這個範例是 reduce 使用方法:

let num = [0, 1, 2, 3, 5, 7].reduce(function(a, b) {
    return a + b;
}, 0);

console.log(num); // 18

也就是進行資料上的加總,而這也是陣列資料蠻常需要做的事。

使用 reduce 扁平化陣列

簡單來說就是,陣列資料如果很多很複雜,reduce 方法可以將陣列資料展開處理;以底下的例子來說,arr 是一個多維陣列,而我們需要使用 reduce 將 arr 變成一維陣列。

let arr = [
    [ 'a','b'  ],
    [ 'c', 'd', 'e' ],
    [ 'f', 'g', 'h' ]
];

// 將所有元素都與之前代入的陣列相接起來,第一次處理時代入初始值空陣列
let newArr = arr.reduce(function(arr, element) {
    return arr.concat(element);
}, []);

console.log(newArr); // ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']

這個函數在這裡會被執行三次,第一次是 a , b 與空陣列相接後回傳,第二次是已經代入的 a , b 與 c , d , e 相接並回傳,第三次是 a , b , c , d , e 與 f , g , h 相接後回傳。

上面的例子可以看到,reduce 可以與前一個回傳的值再次運算。

reduce 實現資料統整與歸納

reduce 也可以統計陣列內容,從範例來看,reduce 方法能計算物件出現的次數。

let arr = [
    '牛肉麵',
    '蛋餅',
    '花椰菜',
    '奶茶',
    '義大利麵',
    '牛肉麵',
    '蛋餅'
];

// 計算出每種語言出現過幾次
let foodNum = arr.reduce(function(langs, langName) {
    if (langs.hasOwnProperty(langName)) {
        langs[langName]++
    } else {
        langs[langName] = 1;
    }
    
    return langs;
}, {});

console.log(foodNum); // {牛肉麵: 2, 蛋餅: 2, 花椰菜: 1, 奶茶: 1, 義大利麵: 1}

不太知道會不會有人跟我有一樣的疑問,但我仍然解釋一下 hasOwnProperty 方法好了。

hasOwnProperty 方法:

會回傳一個布林值,檢視物件自身屬性中是否有指定的屬性,如果具有帶指定名稱的屬性,hasOwnProperty 方法會回傳 true,否則回傳 false。

了解 hasOwnProperty 方法以後,上面範例其實可以猜到,是使用 hasOwnProperty 方法去檢查屬性名稱是否重複,如果重複就會疊加。

reduce 與 Object 形式

這個範例需要使用 Object.keys,keys 代表把物件的屬性抓出來變成陣列,把物件屬性取出來之後,再用名稱回去原物件查值,並且使用 reduce 做加總。

let data = {
    'juice': 5,
    'hamburger': 2,
    'fries': 4,
    'chicken-leg': 10,
    'cola': 2
};

// 使用 Object.keys() 取得包含所有 key 的陣列
let result = Object.keys(data).reduce(function(prev, name) {
    // 利用 key 取得原始物件中的值,然後加總
    return data[name] + prev;
}, 0);

console.log(result); // 23

以上介紹的幾個 reduce 方法執行的小程式,覺得看了就興奮(?),雖然目前還是很簡易的幾個例子,不過可以看得出來在龐大的資料庫裡面,若是使用 reduce 方法,絕對是可以提升不少效率的,這裡已經讓我迫不及待把 reduce 延伸再延伸了,等我研究出更多實務上的寫法,再來與大家分享吧。

參考資料:
上手使用 JavaScript 的 Map、Reduce 吧!
Javascript 中的 for、foreach、 map與reduce的用法


上一篇
JavaScript Day 13. forEach()
下一篇
JavaScript Day 15. every() 與 some()
系列文
我的JavaScript日常31

尚未有邦友留言

立即登入留言