arr.reduce(callback,[initialValue])
复制代码
reduce
为数组中的每个元素依次执行回调函数,不包括数组中被删除或从未被赋值的元素,接受四个参数:初始值(或者上一次回调函数的返回值),当前元素值,当前索引,调用 reduce
的数组。git
callback (执行数组中每一个值的函数,包含四个参数)
1、previousValue (上一次调用回调返回的值(没有提供initialValue),或者是提供的初始值(initialValue))
2、currentValue (数组中当前被处理的元素)
3、index (当前元素在数组中的索引)
4、array (调用 reduce 的数组)
initialValue (做为第一次调用 callback 的第一个参数。)
复制代码
没有提供initialValue参数github
var arr = [1, 2, 3, 4];
var sum = arr.reduce(function(prev, cur, index, arr) {
console.log(prev, cur, index);
return prev + cur;
})
console.log(arr, sum);
// 打印结果:
// 1 2 1
// 3 3 2
// 6 4 3
// [1, 2, 3, 4, 5] 15
复制代码
这里能够看出,上面的例子index是从1开始的,第一次的prev的值是数组的第一个值。数组长度是4,可是reduce函数循环3次。数组
提供initialValue参数安全
var arr = [1, 2, 3, 4];
var sum = arr.reduce(function(prev, cur, index, arr) {
console.log(prev, cur, index);
return prev + cur;
},0) //注意这里设置了初始值
console.log(arr, sum);
// 打印结果:
// 0 1 0
// 1 2 1
// 3 3 2
// 6 4 3
// [1, 2, 3, 4] 10
复制代码
这个例子index是从0开始的,第一次的prev的值是咱们设置的初始值0,数组长度是4,reduce函数循环4次。app
结论:若是没有提供initialValue,reduce 会从索引1的地方开始执行 callback 方法,跳过第一个索引。若是提供initialValue,从索引0开始。
函数
注意:若是这个数组为空,运用reduce
是什么状况?测试
var arr = [];
var sum = arr.reduce(function(prev, cur, index, arr) {
console.log(prev, cur, index);
return prev + cur;
})
//报错,"TypeError: Reduce of empty array with no initial value"
复制代码
可是要是咱们设置了初始值就不会报错,以下:ui
var arr = [];
var sum = arr.reduce(function(prev, cur, index, arr) {
console.log(prev, cur, index);
return prev + cur;
},0)
console.log(arr, sum); // [] 0
复制代码
因此通常来讲咱们提供初始值一般更安全this
计算数组中每一个元素出现的次数spa
let names = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice'];
let nameNum = names.reduce((pre,cur)=>{
if(cur in pre){
pre[cur]++
}else{
pre[cur] = 1
}
return pre
},{})
console.log(nameNum); //{Alice: 2, Bob: 1, Tiff: 1, Bruce: 1}
复制代码
数组去重
let arr = [1,2,3,4,4,1]
let newArr = arr.reduce((pre,cur)=>{
if(!pre.includes(cur)){
return pre.concat(cur)
}else{
return pre
}
},[])
console.log(newArr);// [1, 2, 3, 4]
//-----------------------------------------------
let arr = [1,2,1,2,3,5,4,5,3,4,4,4,4];
let result = arr.sort().reduce((init, current)=>{
if(init.length===0 || init[init.length-1]!==current){
init.push(current);
}
return init;
}, []);
console.log(result); //[1,2,3,4,5]
// 不能使用 pre.push(cur) 由于数组的push方法返回的是新数组的长度,而concat返回的是新数组
复制代码
将二维数组转化为一维
let arr = [[0, 1], [2, 3], [4, 5]]
let newArr = arr.reduce((pre,cur)=>{
return pre.concat(cur)
},[])
console.log(newArr); // [0, 1, 2, 3, 4, 5]
复制代码
将多维数组转化为一维
let arr = [[0, 1], [2, 3], [4,[5,6,7]]]
const newArr = function(arr){
return arr.reduce((pre,cur)=>pre.concat(Array.isArray(cur)?newArr(cur):cur),[])
}
console.log(newArr(arr)); //[0, 1, 2, 3, 4, 5, 6, 7]
复制代码
对象里的属性求和
var result = [
{
subject: 'math',
score: 10
},
{
subject: 'chinese',
score: 20
},
{
subject: 'english',
score: 30
}
];
var sum = result.reduce(function (prev, cur) {
return cur.score + prev;
}, 0);
console.log(sum) //60
复制代码
按属性对object分类
var people = [
{ name: 'Alice', age: 21 },
{ name: 'Max', age: 20 },
{ name: 'Jane', age: 20 }
];
function groupBy(objectArray, property) {
return objectArray.reduce(function (acc, obj) {
console.log(obj)
var key = obj[property];
if (!acc[key]) {
acc[key] = [];
}
acc[key].push(obj);
return acc;
}, {});
}
var groupedPeople = groupBy(people, 'age');
// {
// 20: [
// { name: 'Max', age: 20 },
// { name: 'Jane', age: 20 }
// ],
// 21: [{ name: 'Alice', age: 21 }]
// }
复制代码
功能型函数管道
// Building-blocks to use for composition
const double = x => x + x;
const triple = x => 3 * x;
const quadruple = x => 4 * x;
// Function composition enabling pipe functionality
const pipe = (...functions) => input => functions.reduce(
(acc, fn) => fn(acc),
input
);
// 还原函数
// function pipe(...functions) {
// return function (input) {
// return functions.reduce(function (acc, fn) {
// return fn(acc)
// }, input)
// }
// }
// Composed functions for multiplication of specific values
const multiply6 = pipe(double, triple);
const multiply9 = pipe(triple, triple);
const multiply16 = pipe(quadruple, quadruple);
const multiply24 = pipe(double, triple, quadruple);
// Usage
multiply6(6); // 36
multiply9(9); // 81
multiply16(16); // 256
multiply24(10); // 240
复制代码
filter
为数组中的每一个元素调用一次 callback
函数,并利用全部使得 callback
返回 true 或 等价于 true 的值 的元素建立一个新数组。callback
只会在已经赋值的索引上被调用,对于那些已经被删除或者从未被赋值的索引不会被调用。那些没有经过 callback
测试的元素会被跳过,不会被包含在新数组中。
callback
用来测试数组的每一个元素的函数。调用时使用参数 (element, index, array)。
复制代码
返回true表示保留该元素(经过测试),false则不保留。它接受三个参数:
**element**
当前在数组中处理的元素。
**index**可选
正在处理元素在数组中的索引。
**array**可选
调用了`filter`的数组。
复制代码
thisArg
可选
可选。执行 `callback` 时的用于 `this` 的值。
复制代码
一个新的经过测试的元素的集合的数组,若是没有经过测试则返回空数组
filter
为数组中的每一个元素调用一次 callback
函数,并利用全部使得 callback
返回 true 或 等价于 true 的值 的元素建立一个新数组。callback
只会在已经赋值的索引上被调用,对于那些已经被删除或者从未被赋值的索引不会被调用。那些没有经过 callback
测试的元素会被跳过,不会被包含在新数组中。
callback
被调用时传入三个参数:
若是为 filter
提供一个 thisArg
参数,则它会被做为 callback
被调用时的 this
值。不然,callback
的 this
值在非严格模式下将是全局对象,严格模式下为 undefined
。 callback
最终观察到的this
值是根据一般函数所看到的 "this"的规则肯定的。
filter
不会改变原数组,它返回过滤后的新数组。
filter
遍历的元素范围在第一次调用 callback
以前就已经肯定了。在调用 filter
以后被添加到数组中的元素不会被 filter
遍历到。若是已经存在的元素被改变了,则他们传入 callback
的值是 filter
遍历到它们那一刻的值。被删除或历来未被赋值的元素不会被遍历到。
function isBigEnough(element) {
return element >= 10;
}
var filtered = [12, 5, 8, 130, 44].filter(isBigEnough);
// filtered is [12, 130, 44]
复制代码
var arr = [
{ id: 15 },
{ id: -1 },
{ id: 0 },
{ id: 3 },
{ id: 12.2 },
{ },
{ id: null },
{ id: NaN },
{ id: 'undefined' }
];
var invalidEntries = 0;
function isNumber(obj) {
return obj !== undefined && typeof(obj) === 'number' && !isNaN(obj);
}
function filterByID(item) {
if (isNumber(item.id) && item.id !== 0) {
return true;
}
invalidEntries++;
return false;
}
var arrByID = arr.filter(filterByID);
console.log('Filtered Array\n', arrByID);
// Filtered Array
// [{ id: 15 }, { id: -1 }, { id: 3 }, { id: 12.2 }]
console.log('Number of Invalid Entries = ', invalidEntries);
// Number of Invalid Entries = 5
复制代码
var fruits = ['apple', 'banana', 'grapes', 'mango', 'orange'];
/** * Array filters items based on search criteria (query) */
function filterItems(query) {
return fruits.filter(function(el) {
return el.toLowerCase().indexOf(query.toLowerCase()) > -1;
})
}
console.log(filterItems('ap')); // ['apple', 'grapes']
console.log(filterItems('an')); // ['banana', 'mango', 'orange']
复制代码