删除数组中的奇数

时间:2017-03-31 03:20:06

标签: javascript arrays typescript

我正试图想出另一种方法来从数组中删除所有奇数。一位朋友能够提出这个解决方案,我理解它的作用,但我没有找到另一个解决方案。你对另一个解决方案有什么想法吗?

的JavaScript

let myArray = [1,3,5,7,9,2,4,6,8];
let it = myArray.length;

for(let i=0; i<it; i++) {
  for(let j=0; j<myArray.length; j++ )
    if(myArray[j]%2 === 1){
      myArray.splice(j,1)
      break;
    }
  };

  console.log(myArray);

3 个答案:

答案 0 :(得分:8)

&#13;
&#13;
let myArray = [1, 3, 5, 7, 9, 2, 4, 6, 8];

myArray = myArray.filter(e => e % 2 === 0)

console.log(myArray);
&#13;
&#13;
&#13;

答案 1 :(得分:2)

你的问题是如何“消除赔率”,而不是如何“保持平衡” - 在这种情况下结果是一样的,但你得出答案的方式可能会有所不同。直接插入Array.prototype.filter并不总是有一个完美的相反函数,因此这里的所有答案都将在删除元素的上下文中,我们只能检测奇数值 - 不保持偶数元素。我将详细介绍解决问题的各种方法,但首先让我们回顾一下您的代码

您朋友的回答

我在你的内循环上添加了一个console.log,这样你就可以看到你正在检查的每个元素。很容易看出这个解决方案正在做更多的工作 - 没有必要创建超过 1 循环来迭代你的数字数组。

let myArray = [1,3,5,7,9,2,4,6,8]
let it = myArray.length

for(let i = 0; i < it; i++) {
  for(let j = 0; j < myArray.length; j++ ) {
    console.log('checking:', myArray[j])
    if(myArray[j] % 2 === 1) {
      myArray.splice(j,1)
      break
    }
  }
}

console.log(myArray)

同样重要的是,当你通过迭代来改变数组的长度时,你需要非常谨慎。例如,如果你调用arr.splice(i,1),那对你的循环有什么影响?

  • “i”右侧的所有元素将向左移位1个地方
  • 阵列的长度减少1

那么你的循环应该如何适应呢?

  • 如果拼接后所有元素都向左移动,这意味着我们需要再次检查相同的i,因为它现在指向一个新值
  • 如果长度减少1,我们需要将循环退出条件更改为更快停止1次迭代

以下mutRejectOdds答案解决了这些问题

递归功能

高度可读性和直接但不是堆栈安全

const isOdd = x => x & 1 === 1

const removeOdds = ([x,...xs]) => {
  if (x === undefined)
    return []
  else if (isOdd(x))
    return removeOdds(xs)
  else
    return [x, ...removeOdds(xs)]
}

let data = [1,2,3,4,5,6,7,8]
console.log(removeOdds(data)) // [2,4,6,8]
console.log(data)             // [1,2,3,4,5,6,7,8]

带累加器的线性迭代

堆栈安全且非常实用

const isOdd = x => x & 1 === 1

const removeOdds = xs => {
  let acc = []
  for (let x of xs)
    if (!isOdd(x))
      acc.push(x)
  return acc
}

let data = [1,2,3,4,5,6,7,8]
console.log(removeOdds(data)) // [2,4,6,8]
console.log(data)             // [1,2,3,4,5,6,7,8]

延续传球风格

大脑扭曲,但超级有趣的递归解决方案,可以放在蹦床上,使堆栈安全

const isOdd = x => x & 1 === 1

const identity = x => x

const removeOdds = xs => {
  const aux = ([x,...xs], k) => {
    if (x === undefined)
      return k([])
    else if (isOdd(x))
      return aux(xs, k)
    else
      return aux(xs, acc => k([x, ...acc]))
  }
  return aux(xs, identity)
}

let data = [1,2,3,4,5,6,7,8]
console.log(removeOdds(data)) // [2,4,6,8]
console.log(data)             // [1,2,3,4,5,6,7,8]

高阶函数

类似于递归函数,但是接受另一个参数,它是要跳过的元素的函数 - 可以用线性迭代样式或连续传递样式来编写

const isOdd = x => x & 1 === 1

const reject = (f, [x,...xs]) => {
  if (x === undefined)
    return []
  else if (f(x))
    return reject(f, xs)
  else
    return [x, ...reject(f, xs)]
}

let data = [1,2,3,4,5,6,7,8]
console.log(reject(isOdd, data)) // [2,4,6,8]
console.log(data)                // [1,2,3,4,5,6,7,8]

使用Array.prototype.filter

函数组合

使用高度实用的内置Array.prototype.filter但使用not

的函数组合返回相反的结果

const isOdd = x => x & 1 === 1

const comp = f => g => x => f(g(x))

const not = x => !x

const reject = (f, xs) =>
  xs.filter(comp(not)(f))

let data = [1,2,3,4,5,6,7,8]
console.log(reject(isOdd, data)) // [2,4,6,8]
console.log(data)                // [1,2,3,4,5,6,7,8]

线性迭代与原位突变

我在上面实现的所有方法都会改变原始data - 在某些情况下,如果你有一个特别大的数组并且你不想创建副本< / em>删除了奇数值,您可能希望执行data

的就地修改

此答案解决了原始代码中的问题

const isOdd = x => x & 1 === 1

const mutRejectOdds = xs => {
  for (let i = 0, len = xs.length; i < len; i++)
    if (isOdd(xs[i]))
      (xs.splice(i,1), i--, len--)
}

let data = [1,2,3,4,5,6,7,8]
console.log(mutRejectOdds(data)) // undefined
console.log(data)                // [2,4,6,8]

答案 2 :(得分:0)

如果您只需要支持IE9,您可以使用Array.prototype.filter方法。

var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

var output = arr.filter(function(item) {
    return item % 2 === 0;
});

输出将是过滤值的新数组(仅偶数)。