reduce
_.reduce(list, iteratee, [memo], [context])
Aliases: inject, foldl
别名为 inject 和 foldl, reduce 方法把 list 中元素归结为一个单独的数值。Memo 是 reduce 函数的初始值,会被每一次成功调用 iteratee 函数的返回值所取代 。这个迭代传递4个参数:memo
,value
和 迭代的 index
(或者 key)和最后一个引用的整个 list
。
如果没有 memo 传递给 reduce 的初始调用,iteratee 不会被列表中的第一个元素调用。第一个元素将取代 memo 参数传递给列表中下一个元素调用的 iteratee 函数。
1 2
| var sum = _.reduce([1, 2, 3], function(memo, num){ return memo + num; }, 0); => 6
|
代码实现
reduce.js
1 2 3 4
| import createReduce from './_createReduce.js';
export default createReduce(1);
|
_createReduce.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| import isArrayLike from './_isArrayLike.js'; import keys from './keys.js'; import optimizeCb from './_optimizeCb.js';
export default function createReduce(dir) { var reducer = function(obj, iteratee, memo, initial) { var _keys = !isArrayLike(obj) && keys(obj), length = (_keys || obj).length, index = dir > 0 ? 0 : length - 1; if (!initial) { memo = obj[_keys ? _keys[index] : index]; index += dir; } for (; index >= 0 && index < length; index += dir) { var currentKey = _keys ? _keys[index] : index; memo = iteratee(memo, obj[currentKey], currentKey, obj); } return memo; };
return function(obj, iteratee, memo, context) { var initial = arguments.length >= 3; return reducer(obj, optimizeCb(iteratee, context, 4), memo, initial); }; }
|
_optimizeCb.js
1 2 3 4 5
| case 4: return function(accumulator, value, index, collection) { return func.call(context, accumulator, value, index, collection); };
|
数组reduce方法实现
1 2 3 4 5 6 7 8 9 10
| function reduce(arr,fn,initVal) { let initIndex let acc initIndex = arguments.length === 3 ? 1 : 0 acc = arguments.length === 3 ? initVal : arr[0] for(let initIndex; i < arr.length; i++ ) { acc = fn(acc, arr[i]) } return acc }
|
ReduceRight
1 2 3 4 5
| import createReduce from './_createReduce.js';
export default createReduce(-1);
|