js数组方法reduce经典用法代码分享


Posted in Javascript onJanuary 07, 2018

以下是个人在工作中收藏总结的一些关于javascript数组方法reduce的相关代码片段,后续遇到其他使用这个函数的场景,将会陆续添加,这里作为备忘。

javascript数组那么多方法,为什么我要单挑reduce方法,一个原因是我对这个方法掌握不够,不能够用到随心所欲。另一个方面,我也感觉到了这个方法的庞大魅力,在许多的场景中发挥着神奇的作用。

理解reduce函数

reduce() 方法接收一个函数作为累加器(accumulator),数组中的每个值(从左到右)开始缩减,最终为一个值。

arr.reduce([callback, initialValue])

看如下例子:

let arr = [1, 2, 3, 4, 5];

// 10代表初始值,p代表每一次的累加值,在第一次为10
// 如果不存在初始值,那么p第一次值为1
// 此时累加的结果为15
let sum = arr.reduce((p, c) => p + c, 10); // 25
// 转成es5的写法即为:
var sum = arr.reduce(function(p, c) {
 console.log(p);
 return p + c;
}, 10);

片段一:字母游戏

const anagrams = str => {
 if (str.length <= 2) {
  return str.length === 2 ? [str, str[1] + str[0]] : str;
 }
 return str.split("").reduce((acc, letter, i) => {
  return acc.concat(anagrams(str.slice(0, i) + str.slice(i + 1)).map(val => letter + val));
 }, []);
}

anagrams("abc"); // 结果会是什么呢?

reduce负责筛选出每一次执行的首字母,递归负责对剩下字母的排列组合。

片段二:累加器

const sum = arr => arr.reduce((acc, val) => acc + val, 0);
sum([1, 2, 3]);

片段三:计数器

const countOccurrences = (arr, value) => arr.reduce((a, v) => v === value ? a + 1 : a + 0, 0);
countOccurrences([1, 2, 3, 2, 2, 5, 1], 1);

 

循环数组,每遇到一个值与给定值相等,即加1,同时将加上之后的结果作为下次的初始值。

片段四:函数柯里化

函数柯里化的目的就是为了储存数据,然后在最后一步执行。

const curry = (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(当然也可以自己指定),如果所传的参数比当前参数少,则继续递归下面,同时储存上一次传递的参数。

片段五:数组扁平化

const deepFlatten = arr => 
 arr.reduce((a, v) => a.concat(Array.isArray(v) ? deepFlatten(v) : v), []);
deepFlatten([1, [2, [3, 4, [5, 6]]]]);

片段六:生成菲波列契数组

const fibonacci = n => Array(n).fill(0).reduce((acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i), []);
fibonacci(5);

片段七:管道加工器

const pipe = (...funcs) => arg => funcs.reduce((acc, func) => func(acc), arg);
pipe(btoa, x => x.toUpperCase())("Test");

通过对传递的参数进行函数加工,之后将加工之后的数据作为下一个函数的参数,这样层层传递下去。

片段八:中间件

const dispatch = action => {
 console.log('action', action);
 return action;
}
const middleware1 = dispatch => {
 return action => {
  console.log("middleware1");
  const result = dispatch(action);
  console.log("after middleware1");
  return result;
 }
}
const middleware2 = dispatch => {
 return action => {
  console.log("middleware2");
  const result = dispatch(action);
  console.log("after middleware2");
  return result;
 }
}
const middleware3 = dispatch => {
 return action => {
  console.log("middleware3");
  const result = dispatch(action);
  console.log("after middleware3");
  return result;
 }
}
const compose = middlewares => middlewares.reduce((a, b) => args => a(b(args)))

const middlewares = [middleware1, middleware2, middleware3];
const afterDispatch = compose(middlewares)(dispatch);

const testAction = arg => {
 return { type: "TEST_ACTION", params: arg };
};
afterDispatch(testAction("1111"));

 

redux中经典的compose函数中运用了这种方式,通过对中间件的重重层叠,在真正发起action的时候触发函数执行。
片段九:redux-actions对state的加工片段
// redux-actions/src/handleAction.js
const handleAction = (type, reducer, defaultState) => {
 const types = type.toString();
 const [nextReducer, throwReducer] = [reducer, reducer];
 return (state = defaultState, action) => {
  const { type: actionType } = action;
  if (!actionType || types.indexOf(actionType.toString()) === -1) {
   return state;
  }
  return (action.error === true ? throwReducer : nextReducer)(state, action);
 }
}
// reduce-reducers/src/index.js
const reduceReducer = (...reducers) => {
 return (previous, current) => {
  reducers.reduce((p, r) => r(p, current), previous);
 }
}
// redux-actions/src/handleActions.js
const handleActions = (handlers, defaultState, { namespace } = {}) => {
 // reducers的扁平化
 const flattenedReducerMap = flattenReducerMap(handles, namespace);
 // 每一种ACTION下对应的reducer处理方式
 const reducers = Reflect.ownkeys(flattenedReducerMap).map(type => handleAction(
  type,
  flattenedReducerMap[type],
  defaultState
 ));
 // 状态的加工器,用于对reducer的执行
 const reducer = reduceReducers(...reducers);
 // reducer触发
 return (state = defaultState, action) => reducer(state, action);
}
片段十:数据加工器
const reducers = {
 totalInEuros: (state, item) => {
  return state.euros += item.price * 0.897424392;
 },
 totalInYen: (state, item) => {
  return state.yens += item.price * 113.852;
 }
};
const manageReducers = reducers => {
 return (state, item) => {
  return Object.keys(reducers).reduce((nextState, key) => {
   reducers[key](state, item);
   return state;
  }, {})
 }
}
const bigTotalPriceReducer = manageReducers(reducers);
const initialState = { euros: 0, yens: 0 };
const items = [{ price: 10 }, { price: 120 }, { price: 1000 }];
const totals = items.reduce(bigTotalPriceReducer, initialState);
片段十一:对象空值判断
let school = {
 name: 'Hope middle school',
 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方法
const get = (p, o) => p.reduce((xs, x) => (xs && xs[x] ? xs[x] : null), o);
get(['classes', 0, 'teachers', 0, 'name'], school); // 张二蛋
片段十二:分组
const groupBy = (arr, func) =>
arr.map(typeof func === 'function' ? func : val => val[func]).reduce((acc, val, i) => {
 acc[val] = (acc[val] || []).concat(arr[i]);
 return acc;
}, {});
groupBy([6.1, 4.2, 6.3], Math.floor); 
groupBy(['one', 'two', 'three'], 'length');
首先通过map计算出所有的键值,然后再根据建值进行归类
片段十三:对象过滤
const pick = (obj, arr) =>
arr.reduce((acc, curr) => (curr in obj && (acc[curr] = obj[curr]), acc), {});pick({ a: 1, b: '2', c: 3 }, ['a', 'c']);

根据给出的键值来遍历,比较对象中是否存在相同键值的的值,然后通过逗号表达式把赋值后的对象赋给下一个的初始值

片段十四:数组中删除指定位置的值

const remove = (arr, func) =>
 Array.isArray(arr)
 ? arr.filter(func).reduce((acc, val) => {
   arr.splice(arr.indexOf(val), 1);
   return acc.concat(val);
 }, []) : [];
const arr = [1, 2, 3, 4];
remove(arr, n => n % 2 == 0);

 

首先根据filter函数过滤出数组中符合条件的值,然后使用reduce在原数组中删除符合条件的值,可以得出最后arr的值变成了[1, 3]

片段十五:promise按照顺序执行

const runPromisesInSeries = ps => ps.reduce((p, next) => p.then(next), Promise.resolve());
const delay = d => new Promise(r => setTimeout(r, d));
const print = args => new Promise(r => r(args));
runPromisesInSeries([() => delay(1000), () => delay(2000), () => print('hello')]);

片段十六:排序

const orderBy = (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 < p2 ? -1 : 0;
   }
   return acc;
  }, 0)
 );
const users = [{ name: 'fred', age: 48 }, { name: 'barney', age: 36 }, { name: 'fly', age: 26 }];
orderBy(users, ['name', 'age'], ['asc', 'desc']); 
orderBy(users, ['name', 'age']);

片段十七:选择

const select = (from, selector) =>
 selector.split('.').reduce((prev, cur) => prev && prev[cur], from);
const obj = { selector: { to: { val: 'val to select' } } };
select(obj, 'selector.to.val');

以上就是我们为大家整理的关于js数组方法reduce经典用法代码内容,感谢你对三水点靠木的支持。

Javascript 相关文章推荐
jquery常用特效方法使用示例
Apr 25 Javascript
jQuery使用toggleClass方法动态添加删除Class样式的方法
Mar 26 Javascript
jquery实现叠层3D文字特效代码分享
Aug 21 Javascript
JavaScript高级程序设计(第三版)学习笔记6、7章
Mar 11 Javascript
AngularJS使用ng-repeat和ng-if实现数据的删选显示效果示例【适用于表单数据的显示】
Dec 13 Javascript
gulp安装以及打包合并的方法教程
Nov 19 Javascript
快速处理vue渲染前的显示问题
Mar 05 Javascript
详解ES6 Fetch API HTTP请求实用指南
Nov 14 Javascript
django js 实现表格动态标序号的实例代码
Jul 12 Javascript
vue从零实现一个消息通知组件的方法详解
Mar 16 Javascript
vue3中轻松实现switch功能组件的全过程
Jan 07 Vue.js
vue3 watch和watchEffect的使用以及有哪些区别
Jan 26 Vue.js
javascript中的replace函数(带注释demo)
Jan 07 #Javascript
基于JavaScript实现简单的音频播放功能
Jan 07 #Javascript
js实现复制功能(多种方法集合)
Jan 06 #Javascript
tangram.js库实现js类的方式实例分析
Jan 06 #Javascript
JavaScript寄生组合式继承实例详解
Jan 06 #Javascript
基于jquery trigger函数无法触发a标签的两种解决方法
Jan 06 #jQuery
JS实现非首屏图片延迟加载的示例
Jan 06 #Javascript
You might like
smarty实例教程
2006/11/19 PHP
如何使用PHP往windows中添加用户
2006/12/06 PHP
Windows 下的 PHP-PEAR 安装方法
2010/11/20 PHP
PHP中的session永不过期的解决思路及实现方法分享
2011/04/20 PHP
很让人受教的 提高php代码质量36计
2012/09/05 PHP
基于php上传图片重命名的6种解决方法的详细介绍
2013/04/28 PHP
php 微信公众平台开发模式实现多客服的实例代码
2016/11/07 PHP
JavaScript基本对象
2007/01/11 Javascript
js中获取事件对象的方法小结
2011/03/13 Javascript
实例解析jQuery插件EasyUI最常用的表单验证规则
2015/11/29 Javascript
Bootstrap基本组件学习笔记之面板(14)
2016/12/08 Javascript
JS与jQuery实现ListBox上移,下移,左移,右移操作功能示例
2018/05/31 jQuery
从vue源码解析Vue.set()和this.$set()
2018/08/30 Javascript
老生常谈JavaScript获取CSS样式的方法(兼容各浏览器)
2018/09/19 Javascript
浅谈Vue页面级缓存解决方案feb-alive(上)
2019/04/14 Javascript
javascript网页随机点名实现过程解析
2019/10/15 Javascript
jquery实现垂直手风琴菜单
2020/03/04 jQuery
JavaScript前端实现压缩图片功能
2020/03/06 Javascript
viewer.js实现图片预览功能
2020/06/24 Javascript
vscode自定义vue模板的实现
2021/01/27 Vue.js
python使用PyGame绘制图像并保存为图片文件的方法
2015/04/24 Python
Python文件右键找不到IDLE打开项解决办法
2015/06/08 Python
Python pycharm 同时加载多个项目的方法
2019/01/17 Python
python学生管理系统开发
2019/01/30 Python
使用Python实现将多表分批次从数据库导出到Excel
2020/05/15 Python
canvas之万花筒效果的简单实现(推荐)
2016/08/16 HTML / CSS
个人自我鉴定
2013/11/07 职场文书
党校培训思想汇报
2013/12/30 职场文书
在校大学生的职业生涯规划书
2014/03/14 职场文书
英文请假条
2014/04/11 职场文书
卖车协议书
2014/04/21 职场文书
工商管理专业毕业生求职信
2014/05/26 职场文书
幼儿园班级管理心得体会
2016/01/07 职场文书
Nginx 负载均衡是什么以及该如何配置
2021/03/31 Servers
利用前端HTML+CSS+JS开发简单的TODOLIST功能(记事本)
2021/04/13 Javascript
CSS3新特性详解(五):多列columns column-count和flex布局
2021/04/30 HTML / CSS