如何使用reduce函数简化此代码

时间:2019-03-19 18:29:47

标签: javascript

我有一个数组: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函数的作用,但无法提出任何合乎逻辑的内容。

7 个答案:

答案 0 :(得分: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]));

答案 1 :(得分:1)

 let fiveFound = false;
 const result = input.filter(it => it !== 5 || !(fiveFound = true));
 if(!fiveFound) result.push(5);

reduce在这里无济于事。

答案 2 :(得分:1)

使用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) );

答案 3 :(得分:1)

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

  

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: []}开始,在每个found上将true更新为5,然后将每个非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]

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

答案 4 :(得分:0)

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

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

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

答案 5 :(得分:0)

您可以使用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))

答案 6 :(得分:0)

如果您真的要使用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;
}