【问题标题】:how to use reduce function to simplify this code如何使用reduce函数来简化这段代码
【发布时间】:2019-08-10 09:09:53
【问题描述】:

我有一个数组:var old_array = [1, 2, 3, 4, 5]

如果5存在于这个数组中,删除它,否则添加它。

var new_array = [];
var number_existed = false;
for(var i=0,len=old_array.length;i<len;i++) {
   if(old_array[i] == 5) {
   new_array = old_array.slice(i+1);
   number_existed = true;
   break;
   } else {
      new_array.push( old_array[i] );
   }
}

if(!number_existed) {
    new_array.push(5);
}

它有效,但我需要改进。如何改进此代码。我想看看reduce 函数的实际作用,但就是想不出任何合乎逻辑的东西。

【问题讨论】:

  • 如果在 contains()indexOf() 上并基于此,将其推入数组或拼接出来,为什么不呢?
  • 它有效 ...所以 [1, 1, 5, 1, 1] 应该导致 [1, 1] ?
  • @JonasWilms 是的,我没看到那个来了,谢谢
  • Jeto 的回答应该可以解决这个问题。没有真正的理由为此使用reduce,因为它只会使事情复杂化。如果您只是过滤掉现有的5s,reduce 将是filter 的一个过于复杂但并非不合理的替代方案。但是由于您还想添加5(如果它不存在),因此您的累加器将需要携带额外的状态——否则您会将其存储在更糟糕的地方。这样的代码是可行的,但与替代方案相比相当难看。

标签: javascript


【解决方案1】:

您不需要reduce(),只需使用filter()

var old_array = [1, 2, 3, 4, 5]

var new_array = old_array.filter(x => x === 5);
console.log(new_array);

【讨论】:

    【解决方案2】:
     let fiveFound = false;
     const result = input.filter(it => it !== 5 || !(fiveFound = true));
     if(!fiveFound) result.push(5);
    

    reduce 在这里帮不了你。

    【讨论】:

      【解决方案3】:

      您可以使用Array.includes 检查元素是否已经存在,然后使用Array.filter 将其删除,或者使用spread syntax 附加它:

      function addOrRemove5(arr) {
        return arr.includes(5) ? arr.filter(v => v !== 5) : [...arr, 5];
      }
      
      console.log(addOrRemove5([1, 2, 3, 4, 5]));
      console.log(addOrRemove5([1, 2, 3, 4]));

      【讨论】:

        【解决方案4】:

        您可以使用indexOf 找到它以获取索引,并使用splice 将其删除或使用push 添加它

        var array1 = [1, 2, 3, 4, 5]
        
        function modify_array(value, array) {
          let idx = array.indexOf(value)
          idx > -1 ? array.splice(idx, 1) : array.push(value)
          return array
        }
        
        // Test cases
        
        // Remove 5
        console.log(modify_array(5, array1))
        // Add 10
        console.log(modify_array(10, array1))

        【讨论】:

          【解决方案5】:

          使用reduce 不是最好的方法,因为reduce 用于返回单个项目。在我的解决方案中,我使用 findIndex 并应用您的逻辑。

          function usingFunctions(old) {
          	var index = old.findIndex( function(it) { return it == 5  } );
          	var new_arr = old.slice( index + 1 );
          	if( index < 0 ) new_arr.push(5);
          	return new_arr
          }
          
          var old = [1, 2, 6, 8, 5, 3, 6, 9];
          console.log( usingFunctions(old) );
          old = [1, 2, 6, 8, 3, 6, 9];
          console.log( usingFunctions(old) );

          【讨论】:

            【解决方案6】:

            另一个解决方案,扩展我的评论:

            Jeto 的回答应该可以解决这个问题。没有真正的理由为此使用 reduce,因为它只会使事情复杂化。如果您只是过滤掉现有的 5,reduce 将是filter 的一个过于复杂但并非不合理的替代方案。但是,由于您还想添加一个 5 如果它不存在,那么您的累加器将需要携带额外的状态 - 或者您会将它存储在更糟糕的地方。这样的代码是可行的,但与替代方案相比相当难看。

            下面是这样丑陋的代码的样子:

            const addOrRemove5 = (arr) => { 
              const {found, xs} = arr.reduce(
                ({found, xs}, x) => x === 5 ? {found: true, xs} : {found, xs: [...xs, x]},
                {found: false, xs: []}
              )
              return found ? xs : [...xs, 5]
            }
            
            console.log(addOrRemove5([1, 5, 2, 3, 4, 5])) //=> [1, 2, 3, 4]
            console.log(addOrRemove5([1, 2, 3, 4]))       //=> [1, 2, 3, 4, 5]

            这使用了一个类似于{found: boolean, xs: [number]} 的累加器,从{found: false, xs: []} 开始,将每个5 上的found 更新为true,并将每个非5 值添加到值中。然后在运行之后,我们返回现有值或现有值以及额外的5,具体取决于found 的值。

            同样,这比 Jeto 的解决方案要丑陋得多。我不会在这里推荐它。但是,当您需要携带额外信息并降低价值时,这种技术并不少见。通过将生成的 {found, xs} 对象放在默认参数中,这种变体可以让您仅使用表达式而不使用任何语句:

            const addOrRemove5 = (
              arr, 
              {found, xs} = arr.reduce(
                ({found, xs}, x) => x === 5 ? {found: true, xs} : {found, xs: [...xs, x]},
                {found: false, xs: []}
              )
            ) => found ? xs : [...xs, 5]
            

            同样不建议在这种情况下这样做,但这是一个有用的技巧。

            【讨论】:

              【解决方案7】:

              如果你真的想使用reduce()

                function togglePresenceOfFive(array) {
                if (array.length === 0) { // Reduce can't handle this case because the loop never runs
                      return [5];
                  } else {
                      const reduceResult = array.reduce((acc, next, index, arr) => {
                          const isLast = index === arr.length - 1;
              
                          if (next === 5) {
                              return {
                                  newArray: acc.newArray,
                                  fiveFound: true
                              };
                          } else if (!acc.fiveFound && isLast) {
                              return {
                                  newArray: acc.newArray.concat(next, 5),
                                  fiveFound: false
                              }
                          } else {
                              return {
                                  newArray: acc.newArray.concat(next),
                                  fiveFound: acc.fiveFound
                              };
                          }
                          },
                          { newArray: [], fiveFound: false }
                      );
              
                      return reduceResult.newArray; 
                  }
              }
              
                return reduceResult.newArray;
              }
              

              但在我看来,这更具可读性(假设您不介意改变原始数组):

              function togglePresenceOfFive(array) {
                  const indexOfFive = array.indexOf(5);
              
                  if (indexOfFive > -1) {
                      array.splice(indexOfFive, 1);
                  } else {
                      array.push(5);
                  }
              
                  return array;
              }
              

              【讨论】:

              • 查看我的答案以获得相同 reduce 想法的更简洁版本。它还通过给累加器一个起始值来处理空数组的情况。但当然,重点是这可能有点矫枉过正。
              猜你喜欢
              • 1970-01-01
              • 2022-11-14
              • 1970-01-01
              • 1970-01-01
              • 2018-03-24
              • 2021-04-28
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多