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的用法


<<:  [ 卡卡 DAY 8 ] - React Native 跨平台装置判断

>>:  [Day23] Angular 简介

Day 20. slate × Operation × Interface

我们接下来就要进入到 slate 世界里的另一大领域: Operations 。 这一整段章节其实...

《Day30》MySQL Replication GTID

MySQL 从5.6.5开始支援GTID(global transaction identified...

操作授权 (Authorization to Operate:ATO)

-NIST SDLC 和 RMF RMF:授权系统( Authorize System) 授权是授...

那些被忽略但很好用的 Web API / SessionStorage

狡兔有三窟,储存用户端的资料当然也要有三个。 相信大家应该都有遇过需要将资料储存在用户端的需求,像...

How to Prepare For SAP C_TPLM30_67 Exam?

SAP C_TPLM30_67 is the third version of SAP C_TPLM...