我正在做一个基于 underscore.js 的 reduce 练习的练习。 现在,我有了一个可行的解决方案,但我相信它可以做得更好,因为我在 Frankenstein 解决方案中使用了大量复制粘贴。
这是我想出的解决方案:
_.reduce = function (collection, iteratee, accumulator, context) {
if (Array.isArray(collection)) {
var returnVal = accumulator !== undefined ? accumulator : collection[0];
if (accumulator !== undefined) {
for (var i = 0; i < collection.length; i++) {
returnVal = iteratee.call(
context,
returnVal,
collection[i],
i,
collection
);
}
} else {
for (var i = 1; i < collection.length; i++) {
returnVal = iteratee.call(
context,
returnVal,
collection[i],
i,
collection
);
}
}
console.log(returnVal);
return returnVal;
} else if (typeof collection === "object") {
var keys = Object.keys(collection);
var returnVal =
accumulator !== undefined ? accumulator : collection[keys[0]];
if (accumulator !== undefined) {
for (var i = 0; i < keys.length; i++) {
returnVal = iteratee.call(
context,
returnVal,
collection[keys[i]],
keys[i],
collection
);
}
} else {
for (var i = 1; i < keys.length; i++) {
returnVal = iteratee.call(
context,
returnVal,
collection[keys[i]],
keys[i],
collection
);
}
}
console.log(returnVal);
return returnVal;
}
};
如您所见,我区分了作为数组的集合和作为对象的集合。这是我的第一个条件。在这个条件中,我对数组和对象都有另一个条件。此条件检查
accumulator
是否未定义。如果 true
,则运行第一次迭代中的 for loop
,如果 false
,则运行第二次迭代中的 for loop
。我这样做是因为当累加器未定义时,它必须是集合中的第一个值,如果我从第一次迭代中运行 for loop
,第一个值将显示为双倍。
我尝试在
for loop
内添加条件来检查accumulator
是否是undefined
,如果是undefined
我会continue
。然而这不起作用,因为累加器显然保持 undefined
。
我还尝试在
for loop
中添加该条件,并从第二次迭代开始 for loop
,条件将手动将集合的第一个值添加到 returnVal
(如果 accumulator
是 undefined
) 。这也不起作用,因为它弄乱了结果并以错误的顺序返回。
我不知道这是否可能,但我想缩短我的代码以使其更具可读性,并且总体上是更好的代码。我认为可以缩短这段代码,我只是看不出在哪里以及如何缩短。如果还有任何其他改进需要进行,我很乐意听到它们,因为这将帮助我成为一名更好的编码员!!
提前致谢。
ps。我无法使用
forEach()
、map()
、reduce()
和 filter()
等内置函数。
这是一个简化的代码。它使用单个
for
循环,根据 i
是否为 accumulator
来设置初始索引 undefined
。如果 accumulator
未定义,则从索引 1
开始,跳过第一次迭代。如果定义了accumulator
,它将从索引0
开始,包括第一次迭代。而且最好使用 let
而不是 var
。
_.reduce = function (collection, iteratee, accumulator, context) {
let returnVal, i, keys;
if (Array.isArray(collection)) {
returnVal = accumulator !== undefined ? accumulator : collection[0];
i = accumulator !== undefined ? 0 : 1;
for (; i < collection.length; i++) {
returnVal = iteratee.call(context, returnVal, collection[i], i, collection);
}
return returnVal;
}
if (typeof collection === "object") {
keys = Object.keys(collection);
returnVal = accumulator !== undefined ? accumulator : collection[keys[0]];
i = accumulator !== undefined ? 0 : 1;
for (; i < keys.length; i++) {
returnVal = iteratee.call(context, returnVal, collection[keys[i]], keys[i], collection);
}
return returnVal;
}
};