js数组方法reduce经典用法代码分享
以下是个人在工作中收藏总结的一些关于javascript数组方法reduce的相关代码片段,后续遇到其他使用这个函数的场景,将会陆续添加,这里作为备忘。
javascript数组那么多方法,为什么我要单挑reduce方法,一个原因是我对这个方法掌握不够,不能够用到随心所欲。另一个方面,我也感觉到了这个方法的庞大魅力,在许多的场景中发挥着神奇的作用。
理解reduce函数
reduce()方法接收一个函数作为累加器(accumulator),数组中的每个值(从左到右)开始缩减,最终为一个值。
arr.reduce([callback,initialValue])
看如下例子:
letarr=[1,2,3,4,5]; //10代表初始值,p代表每一次的累加值,在第一次为10 //如果不存在初始值,那么p第一次值为1 //此时累加的结果为15 letsum=arr.reduce((p,c)=>p+c,10);//25 //转成es5的写法即为: varsum=arr.reduce(function(p,c){ console.log(p); returnp+c; },10);
片段一:字母游戏
constanagrams=str=>{ if(str.length<=2){ returnstr.length===2?[str,str[1]+str[0]]:str; } returnstr.split("").reduce((acc,letter,i)=>{ returnacc.concat(anagrams(str.slice(0,i)+str.slice(i+1)).map(val=>letter+val)); },[]); } anagrams("abc");//结果会是什么呢?
reduce负责筛选出每一次执行的首字母,递归负责对剩下字母的排列组合。
片段二:累加器
constsum=arr=>arr.reduce((acc,val)=>acc+val,0); sum([1,2,3]);
片段三:计数器
constcountOccurrences=(arr,value)=>arr.reduce((a,v)=>v===value?a+1:a+0,0); countOccurrences([1,2,3,2,2,5,1],1);
循环数组,每遇到一个值与给定值相等,即加1,同时将加上之后的结果作为下次的初始值。
片段四:函数柯里化
函数柯里化的目的就是为了储存数据,然后在最后一步执行。
constcurry=(fn,arity=fn.length,...args)=> arity<=args.length?fn(...args):curry.bind(null,fn,arity,...args); curry(Math.pow)(2)(10); curry(Math.min,3)(10)(50)(2);
通过判断函数的参数取得当前函数的length(当然也可以自己指定),如果所传的参数比当前参数少,则继续递归下面,同时储存上一次传递的参数。
片段五:数组扁平化
constdeepFlatten=arr=> arr.reduce((a,v)=>a.concat(Array.isArray(v)?deepFlatten(v):v),[]); deepFlatten([1,[2,[3,4,[5,6]]]]);
片段六:生成菲波列契数组
constfibonacci=n=>Array(n).fill(0).reduce((acc,val,i)=>acc.concat(i>1?acc[i-1]+acc[i-2]:i),[]); fibonacci(5);
片段七:管道加工器
constpipe=(...funcs)=>arg=>funcs.reduce((acc,func)=>func(acc),arg); pipe(btoa,x=>x.toUpperCase())("Test");
通过对传递的参数进行函数加工,之后将加工之后的数据作为下一个函数的参数,这样层层传递下去。
片段八:中间件
constdispatch=action=>{ console.log('action',action); returnaction; } constmiddleware1=dispatch=>{ returnaction=>{ console.log("middleware1"); constresult=dispatch(action); console.log("aftermiddleware1"); returnresult; } } constmiddleware2=dispatch=>{ returnaction=>{ console.log("middleware2"); constresult=dispatch(action); console.log("aftermiddleware2"); returnresult; } } constmiddleware3=dispatch=>{ returnaction=>{ console.log("middleware3"); constresult=dispatch(action); console.log("aftermiddleware3"); returnresult; } } constcompose=middlewares=>middlewares.reduce((a,b)=>args=>a(b(args))) constmiddlewares=[middleware1,middleware2,middleware3]; constafterDispatch=compose(middlewares)(dispatch); consttestAction=arg=>{ return{type:"TEST_ACTION",params:arg}; }; afterDispatch(testAction("1111"));
redux中经典的compose函数中运用了这种方式,通过对中间件的重重层叠,在真正发起action的时候触发函数执行。 片段九:redux-actions对state的加工片段
//redux-actions/src/handleAction.js consthandleAction=(type,reducer,defaultState)=>{ consttypes=type.toString(); const[nextReducer,throwReducer]=[reducer,reducer]; return(state=defaultState,action)=>{ const{type:actionType}=action; if(!actionType||types.indexOf(actionType.toString())===-1){ returnstate; } return(action.error===true?throwReducer:nextReducer)(state,action); } } //reduce-reducers/src/index.js constreduceReducer=(...reducers)=>{ return(previous,current)=>{ reducers.reduce((p,r)=>r(p,current),previous); } } //redux-actions/src/handleActions.js consthandleActions=(handlers,defaultState,{namespace}={})=>{ //reducers的扁平化 constflattenedReducerMap=flattenReducerMap(handles,namespace); //每一种ACTION下对应的reducer处理方式 constreducers=Reflect.ownkeys(flattenedReducerMap).map(type=>handleAction( type, flattenedReducerMap[type], defaultState )); //状态的加工器,用于对reducer的执行 constreducer=reduceReducers(...reducers); //reducer触发 return(state=defaultState,action)=>reducer(state,action); }片段十:数据加工器
constreducers={ totalInEuros:(state,item)=>{ returnstate.euros+=item.price*0.897424392; }, totalInYen:(state,item)=>{ returnstate.yens+=item.price*113.852; } }; constmanageReducers=reducers=>{ return(state,item)=>{ returnObject.keys(reducers).reduce((nextState,key)=>{ reducers[key](state,item); returnstate; },{}) } } constbigTotalPriceReducer=manageReducers(reducers); constinitialState={euros:0,yens:0}; constitems=[{price:10},{price:120},{price:1000}]; consttotals=items.reduce(bigTotalPriceReducer,initialState);片段十一:对象空值判断
letschool={ name:'Hopemiddleschool', created:'2001', classes:[ { name:'三年二班', teachers:[ {name:'张二蛋',age:26,sex:'男',actor:'班主任'}, {name:'王小妞',age:23,sex:'女',actor:'英语老师'} ] }, { name:'明星班', teachers:[ {name:'欧阳娜娜',age:29,sex:'女',actor:'班主任'}, {name:'李易峰',age:28,sex:'男',actor:'体育老师'}, {name:'杨幂',age:111,sex:'女',actor:'艺术老师'} ] } ] }; //常规做法 school.classes&& school.classes[0]&& school.classes[0].teachers&& school.classes[0].teachers[0]&& school.classes[0].teachers[0].name //reduce方法 constget=(p,o)=>p.reduce((xs,x)=>(xs&&xs[x]?xs[x]:null),o); get(['classes',0,'teachers',0,'name'],school);//张二蛋片段十二:分组
constgroupBy=(arr,func)=> arr.map(typeoffunc==='function'?func:val=>val[func]).reduce((acc,val,i)=>{ acc[val]=(acc[val]||[]).concat(arr[i]); returnacc; },{}); groupBy([6.1,4.2,6.3],Math.floor); groupBy(['one','two','three'],'length');首先通过map计算出所有的键值,然后再根据建值进行归类 片段十三:对象过滤
constpick=(obj,arr)=>
arr.reduce((acc,curr)=>(currinobj&&(acc[curr]=obj[curr]),acc),{});pick({a:1,b:'2',c:3},['a','c']);
constremove=(arr,func)=> Array.isArray(arr) ?arr.filter(func).reduce((acc,val)=>{ arr.splice(arr.indexOf(val),1); returnacc.concat(val); },[]):[]; constarr=[1,2,3,4]; remove(arr,n=>n%2==0);
construnPromisesInSeries=ps=>ps.reduce((p,next)=>p.then(next),Promise.resolve()); constdelay=d=>newPromise(r=>setTimeout(r,d)); constprint=args=>newPromise(r=>r(args)); runPromisesInSeries([()=>delay(1000),()=>delay(2000),()=>print('hello')]);
constorderBy=(arr,props,orders)=> [...arr].sort((a,b)=> props.reduce((acc,prop,i)=>{ if(acc===0){ const[p1,p2]=orders&&orders[i]==='desc'?[b[prop],a[prop]]:[a[prop],b[prop]]; acc=p1>p2?1:p1片段十七:选择 constselect=(from,selector)=> selector.split('.').reduce((prev,cur)=>prev&&prev[cur],from); constobj={selector:{to:{val:'valtoselect'}}}; select(obj,'selector.to.val');以上就是我们为大家整理的关于js数组方法reduce经典用法代码内容,感谢你对毛票票的支持。