当一个参数未定义时如何跳过第一次迭代?

问题描述 投票:0回答:1

我正在做一个基于 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()
等内置函数。

javascript conditional-statements underscore.js
1个回答
0
投票

这是一个简化的代码。它使用单个

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;
    }
  };
© www.soinside.com 2019 - 2024. All rights reserved.