-
函数定义
数组的高阶函数reduce:
arr.reduce(function(array,prev,cur,index){})
prev:上一次调用的返回值,默认为0,可以使用reduce的第二个参数设置默认初始值。
cur:当前的数组值
-
常用代码:
1.去重
var array = [1,2,3,2,3,4];
var diffarr = arr => arr.reduce((prev,cur)=>{(prev.indexOf(cur)===-1)&&prev.push(cur);return prev;},[]);
console.log(diffarr(array));//[ 1, 2, 3, 4 ]
2.(按照深度)扁平化数组
const flattenarr = (array,depth = 1) =>
array.reduce((prev,cur) =>
prev.concat(depth > 1 && Array.isArray(cur) ? flattenarr(cur,depth - 1):cur),[]);
扁平化:
concat+map
reduce+concat
const deepflatten = arr => [].concat(...arr.map(v=>(Array.isArray(v)?deepflatten(v):v)));
const flat = arr => arr.reduce((acc,val)=>acc.concat(Array.isArray(val)?flat(val):val),[])
console.log("flat",flat([1,[1,2,3],3,[2,3,[2]]]));//[ 1, 1, 2, 3, 3, 2, 3, 2 ]
3.数组切块
Array.from(伪数组/可迭代对象,函数,this);
// Generate a sequence of numbers
// Since the array is initialized with `undefined` on each position,
// the value of `v` below will be `undefined`
Array.from({length: 5}, (v, i) => i);
// [0, 1, 2, 3, 4]
// 切分数组为小块
// chunk([1, 2, 3, 4, 5], 2); // [[1,2],[3,4],[5]]
const chunk = (arr,size) => Array.from({length:Math.ceil(arr.length/size)},(v,i)=>arr.slice(i*size,i*size+size));//i:0,1,2
console.log(chunk1([1, 2, 3, 4, 5], 2));
function chunk1(arr,size){
let newarr = [];
for (var i = 0; i < arr.length; i+=size) {
newarr.push(arr.slice(i,i+size));
}
return newarr;
}
4.合并去重
concat(arr1,arr2);
[].concat.apply([],arguments);
//去重合并
function combine(){
let arr = [].concat.apply([],arguments);
return Array.from(new Set(arr));
}
var m = [1, 2, 2], n = [2,3,3],p=[2,3,5];
console.log(combine(m,n,p)); //[ 1, 2, 3, 5 ]
5.过滤假值(‘’,0,null,undefine,NAN)
const compact = arr => arr.filter(Boolean);
6.按照规则计数
acc[val] = (acc[val]||0)+1;这行好厉害呀,节省了好多代码
const countBy = (arr,fn)=>
arr.map(typeof fn ==="function" ? fn:val=>val[fn]).reduce((acc,val)=>{
acc[val] = (acc[val]||0)+1;
return acc;
},{});
console.log(countBy(['one', 'two', 'three'], 'length'));// {3: 2, 5: 1}
console.log(countBy([6.1, 4.2, 6.3], Math.floor)); // {4: 1, 6: 2}
7.差集,交集
在a中,不再b中
交集则,x=>s.has(x)
const diff = (a,b)=>{//在a中,不在b中
const s = new Set(b);
return a.filter(x=>!s.has(x));
}
var m = [1, 2, 4], n = [2,3,3];
console.log(diff(m,p));//[ 1, 4 ]
Array.prototype.findIndex()
8.头删n个
arr.slice(n);
9.奇数,偶数
const even = arr =>arr.filter((e,i)=>i%2===1)//偶数,索引0,1,2...
console.log(even([1,2,3,4,5,6,7,8]));//[ 2, 4, 6, 8 ]
const odd = arr =>arr.filter((e,i)=>i%2===0)//奇数,索引0,1,2...
console.log(odd([1,2,3,4,5,6,7,8]));//[ 1, 3, 5, 7 ]
10.数组中出现一次的数
const filterNonUnique = arr => arr.filter((e)=>arr.indexOf(e)===arr.lastIndexOf(e));
console.log(filterNonUnique([1,2,2,3,3,4,4,5,6]));//[1,5,6]
11.indexOfAll 找出某个值的所有索引
Returns all indices of val
in an array. If val
never occurs, returns []
.
比较当前值和给定的el,找到则返回[...acc,i](即i push到acc),否则返回acc
acc.push(i) ===============acc = [...acc,i]
const indexOfAll2 = (arr,el)=>arr.reduce((acc,val,i)=>(val===el&&acc.push(i),acc),[]);
const indexOfAll = (arr,el)=>arr.reduce((acc,val,i)=>(val===el?[...acc,i]:acc),[]);
console.log(indexOfAll([1,2,2,3,3,4,4,5,2,6],2));//[1,2,8]
12使用函数将数组的值映射到对象,其中键值对由字符串化的值作为键和映射的值组成。
const squareIt = arr => mapObject(arr, a => a * a);
squareIt([1, 2, 3]); // { 1: 1, 2: 4, 3: 9 }
先将执行一边fn函数,[arr,fn(arr)]存为二维数组。reduce二维数组的arr,返回值对象acc赋值为acc[当前值]=fn(arr)[index]
使用匿名内部函数作用域声明未定义的内存空间,使用闭包存储返回值。使用一个新的数组来存储该数组,其中包含函数在其数据集上的映射,并使用逗号操作符返回第二个步骤,而不需要从一个上下文移动到另一个上下文(由于闭包和操作顺序)。
const mapObject = (arr,fn)=>
(a=>(a=[arr,arr.map(fn)],a[0].reduce((acc,val,index)=>(acc[val]=a[1][index],acc),{})))();
const squareIt = arr => mapObject(arr, a => a * a);
console.log(squareIt([1, 2, 3])); // { 1: 1, 2: 4, 3: 9 }
13.topK
const maxN = (arr, n = 1) => [...arr].sort((a, b) => b - a).slice(0, n);
14.数组的第n个元素
const nthElement = (arr, n = 0) => (n === -1 ? arr.slice(n) : arr.slice(n, n + 1))[0];
15.移动n个元素到末尾
const offset = (arr, offset) => [...arr.slice(offset), ...arr.slice(0, offset)];
16.按照给定函数划分,满足函数要求acc[0],否则acc[1]
acc[fn(val)?0:1].push(val),这里使用的很简洁,好评!
const partition = (arr,fn)=>arr.reduce((acc,val)=>{
acc[fn(val)?0:1].push(val);
return acc;
},[[],[]])
const users = [
{ user: 'barney', age: 36, active: false },
{ user: 'fred', age: 40, active: true },
{ user: 'mary', age:24, active: true }];
console.log(partition(users, o => o.active));
//[ [ { user: 'fred', age: 40, active: true },
// { user: 'mary', age: 24, active: true } ],
// [ { user: 'barney', age: 36, active: false } ] ]
17.全排列
长度小于等于2直接给出结果,即递归出口。
const permutations = arr => {
if(arr.length <= 2) return arr.length ===2?[arr,[arr[1],arr[0]]]:arr;
return arr.reduce((acc,val,i)=>
acc.concat(permutations([...arr.slice(0,i),...arr.slice(i+1)]).map(el=>[val,...el])
//取出arr[i],计算剩下元素构成的全排列,利用map函数对计算的每个排列结果的前面都插入arr[i].
)
,[]);
}
console.log(permutations([1,2,3]));
//[ [ 1, 2, 3 ],[ 1, 3, 2 ],[ 2, 1, 3 ],[ 2, 3, 1 ], [ 3, 1, 2 ],[ 3, 2, 1 ] ]
18.过滤掉指定数值,返回新数组,传入的为数组或者数值
let myArray = ['a', 'b', 'c', 'a', 'b', 'c'];
pull(myArray, 'a', 'c'); // myArray = [ 'b', 'b' ]
19.根据条件过滤对象数组,同时过滤掉未指定的键。
const data = [
{
id: 1,
name: 'john',
age: 24
},
{
id: 2,
name: 'mike',
age: 50
}
];
reducedFilter(data, ['id', 'name'], item => item.age > 24); // [{ id: 2, name: 'mike'}]
使用array .prototype.filter()根据fn对数组进行过滤,以便它返回条件为其返回true值的对象。在经过筛选的数组上,使用array .prototype.map()返回新对象,使用array .prototype.reduce()过滤掉没有作为键参数提供的键。
const reducedFilter = (arr,filteritems,fn)=>
arr.filter(fn).map(el => filteritems.reduce((acc,val)=>{
acc[val] = el[val];
return acc;
},{}));
const data = [
{
id: 1,
name: 'john',
age: 24
},
{
id: 2,
name: 'mike',
age: 50
},
{
id: 3,
name: 'nick',
age: 28
},
];
// [ { id: 2, name: 'mike' }, { id: 3, name: 'nick' } ]
console.log(reducedFilter(data, ['id', 'name'], item => item.age > 24));
19.从给定函数返回false的数组中移除元素。
remove([1, 2, 3, 4], n => n % 2 === 0); // [2, 4]
//修改原数组
const remove = (arr,fn)=>Array.isArray(arr)?arr.filter(fn).reduce((acc,val)=>{
arr.splice(arr.indexOf(val),1);
return acc.concat(val);
},[]):[];
//不修改原数组
const remove = (arr,fn)=>arr.filter(fn);
console.log(remove([1, 2, 3, 4], n => n % 2 === 0)); // [2, 4]
20.提取url的参数列表为对象
var url = "/test/demo_form.php?name1=value1&name2=value2";
var urlquery = url.split("?").slice(-1).toString();
let obj = urlquery.split("&").reduce((acc,cur)=> {
acc[cur.split("=")[0]] = cur.split("=")[1];
return acc;
},{});
console.log(obj);//{ name1: 'value1', name2: 'value2' }