Javascript 中的map/reduce

看到一个发问的回复奇妙地运用了map/reduce操纵,很文雅,所以来进修和总结一下javascript自带的map/reduce的运用技能,文章不会讲的很深,纯当科普一下知识点,若有诠释的不正确的处所,迎接斧正。

1.map

1.1 要领概述

map() 要领经由过程对原数组中的每一个元素举行肯定的操纵(配合挪用一个要领),返回一个新的数组。

1.2 简朴例子

/**
 * 每一个数组元素乘以2输出
 */
var arr1 = [1,2,3,4];
var arr2 = arr1.map(x => {
    return x * 2;
});
console.log(arr2);    // [2,4,6,8]


/**
 * 输出'Hello World'每一个字符所对应的 ASCII 码构成的数组:
 */
var a = [].map.call("Hello World", x => {
    return x.charCodeAt(0); 
})
console.log(a);   //[72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100]

*注:

  1. [ ].map.call() 能够写成 Array.prototype.map.call(); 不懂的能够参看之前的一篇文章:nodejs中call和apply的进修
  2. map函数不改变数组自身:

    var arr = [1,2,3,4];
    arr.map(x => { return Math.sqrt(x) });
    console.log(arr); //[1,2,3,4] 而不是[1, 1.414…, 1.732…, 2]

1.3 语法诠释

var new_array = old_array.map(callback, [thisArg]);

个中
callback是天生新数组元素的函数,运用三个参数:

  • currentValue: callback 的第一个参数,数组中正在处置惩罚的当前元素。
  • index: callback 的第二个参数,数组中正在处置惩罚的当前元素的索引。
  • array: callback 的第三个参数,map 要领被挪用的数组。

thisArg是可选的。实行 callback 函数时 运用的this 值。
返回值new_array :一个新数组,每一个元素都是回调函数的结果。

关于[“1”, “2”, “3”].map(parseInt)语句会输出什么呢?你能够觉的会是[1, 2, 3],但现实的结果是 [1, NaN, NaN],一般运用parseInt时,只需要通报一个参数,但现实上,parseInt能够有两个参数,第二个参数是进制数,能够经由过程语句”alert(parseInt.length)===2″来考证。map要领在挪用callback函数时,会给它通报三个参数:当前正在遍历的元素, 元素索引, 原数组自身。第三个参数parseInt会无视, 但第二个参数不会,也就是说,parseInt把传过来的索引值当做进制数来运用.从而返回了NaN.

function returnInt(element){
    return parseInt(element,10);
}

["1", "2", "3"].map(returnInt);   // 返回[1,2,3]

2.reduce

2.1 要领概述

reduce() 要领对累加器和数组的每一个值 (从左到右)运用一个函数,以将其削减为单个值。内部完成应该是遍历元素,理论上能够经由过程forEach要领完成其功用。

2.2 简朴例子

reduce一个较为经常使用的场景就是累加或累乘:

/**
 * 输出数组元素的乘积:
 */
var arr = [1,2,3];

var reducer = function add(stepProduct, item) { 
    return stepProduct * item; 
};

var product = arr.reduce(reducer, 1);

console.log(product);     //6


/**
 * 输出数组元素的乘积(简写情势):
 */
var product = [1,2,3].reduce((stepProduct, item) => {
    return stepProduct * item;
},1);
console.log(product);


/**
 * 输出数组元素的乘积(call情势,营建庞杂的逼格):
 */
var product = [].reduce.call([1,2,3], (stepProduct, item) => {
    return stepProduct * item;
},1);
console.log(product);

reduce用在数组降维(扁平化处置惩罚)的例子中:

var list1 = [[0, 1], [2, 3], [4, 5]];
var list2 = [0, [1, [2, [3, [4, [5, [6]]]]]]];

function flatten(arr){
    return arr.reduce((acc, val) => {
        return acc.concat(Array.isArray(val) ? flatten(val) : val)
    }, []);
};

console.log(flatten(list1));  // [0, 1, 2, 3, 4, 5]
console.log(flatten(list2));  // [0, 1, 2, 3, 4, 5, 6]

*注:

  1. concat() 要领用于衔接两个或多个数组。用法拜见:JavaScript concat() 要领
  2. flatten用于数组降维。用法拜见:JavaScript Array Flatten 与递归运用引见_javascript技能

回到文章一最先说起的一道问题,问题是如许的:寻觅字符串中涌现次数起码的、而且初次涌现位置最前的字符。如cbaacfdeaebb,符合要求的是f。个中一个用reduce来解决计划(姑且不评价是不是最优计划):

var str = [].reduce.call('cbaacfdeaebb', (p, n) => {
    return p[n] = (p[n] || 0) + 1,p;
},{});   // {c: 2, b: 3, a: 3, f: 1, d: 1, e: 2}

var s = Object.keys(str).reduce(function(p,n){
    return str[p] <= str[n] ? p : n;
});   //1

console.log(s,str[s]); 

/*
 * 以下是上面要领地球人比较轻易看懂的改写体式格局(写完觉得好过剩,蜜汁为难T_T):
 */
var str = 'cbaacfdeaebb'.split('').reduce((allItems, item) => {
    allItems[item] = (allItems[item] || 0) + 1;
    return allItems;
},{});   // {c: 2, b: 3, a: 3, f: 1, d: 1, e: 2}

*注:

return p[n] = (p[n] || 0) + 1,p; 是两句代码的简写情势:
p[n] = (p[n] || 0) + 1;
return p;

2.3 语法诠释

arr.reduce(callback, [initialValue])

个中
callback是实行数组中每一个值的函数,包括四个参数

  • accumulator: 上一次挪用回调返回的值,或者是供应的初始值(initialValue)
  • currentValue: 数组中正在处置惩罚的元素
  • currentIndex: 数据中正在处置惩罚的元素索引,假如供应了 initialValue ,从0最先;否则从1最先
  • array: 挪用 reduce 的数组

函数返回函数累计处置惩罚的结果。

initialValue为可选项,其值用于第一次挪用 callback 的第一个参数。

3 总结

map/reduce是ECMAScript5范例中涌现的数组要领,在处置惩罚数组的时刻奇妙地运用能够到达意想不到的结果,引荐mozilla的手艺文档,体系引见了种种函数的运用要领,个中map/reduce在Array面前目今。
文中若有毛病,迎接批评指出。(ಡωಡ)

    原文作者:芒果屋里的猫
    原文地址: https://segmentfault.com/a/1190000008719824
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞