删除数组中的奇数 [英] Remove odd numbers in array

查看:120
本文介绍了删除数组中的奇数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



JavaScript

 让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);


解决方案

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



您朋友的回答



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



  let myArray = [1,3,5,7,9,2,4,6,8] let it = myArray.lengthfor(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 === 1const 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 === 1const 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]  






继续传递风格



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



< pre class =snippet-code-js lang-js prettyprint-override> const isOdd = x => x& 1 === 1const identity = x => xconst removeOdds = xs => {const aux =([x,... xs],k)=> {if(x === undefined)返回k([])否则if(isOdd(x))返回aux(xs,k)否则返回aux(xs,acc => k([x,... acc] ))}返回aux(xs,identity)} let data = [1,2,3,4,5,6,7,8] console.log(removeOdds(data))// [2,4,6,8 ] console.log(数据)// [1,2,3,4,5,6,7,8]






高阶函数



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



  const isOdd = x => x& 1 === 1const 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 但使用函数组合返回相反的结果



  const isOdd = x => x& 1 === 1const comp = f => g => x => f(g(x))const not = x => !xconst 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(数据)// [1,2,3,4,5,6,7,8]  






线性迭代与原位突变



我上面实现的所有方法都改变了原来的数据 - 在某些情况下,如果你有一个特别大的数组,您不想创建删除了奇数值的副本,您可能希望执行数据的就地修改



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



  const isOdd = x => x& 1 === 1const 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))// undefinedconsole.log(data)// [2,4,6,8]  


I am trying to come up with another way to remove all of the odd numbers from an array. A friend was able to come up with this solution and I understand what it does, but I am failing to find another solution to it. Do you have any ideas for another solution to do this?

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

解决方案

Your question asks how to "remove odds", not how to "keep evens" – the result is the same in this case, but the way you derive the answer could vary. There's not always a perfect opposite function that plugs directly into Array.prototype.filter, so all answers here will be in the context of removing elements where we only a way to detect odd values – not keeping elements that are even. I'll detail a wide variety of ways to solve your problem, but first let's review your code

your friend's answer

I added a console.log on your inner loop so you can see each element you're checking. It's easy to see that this solution is doing more work than it has to - there's no need to create more than 1 loop to iterate thru your array of numbers.

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)

Also important, you need to be very mindful when changing the length of an array as you're iterating thru it. For example, if you call arr.splice(i,1), what effect does that have on your loop?

  • all elements to the right of "i" will shift left 1 place
  • the length of the array decreases by 1

So how should your loop accommodate for that?

  • if all elements shift left after a splice, that means we need to re-check the same i once more because it now points to a new value
  • if the length decreases by 1, we need to change the loop exit condition to stop 1 iteration sooner

The mutRejectOdds answer below addresses these issues


recursive function

highly readable and straightforward but not stack-safe

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]


linear iterative with accumulator

stack-safe and highly practical

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]


continuation passing style

brain-twisting but super fun recursive solution that could be put on a trampoline to make stack-safe

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]


higher-order function

similar to the recursive function, but instead accepts another argument which is a function of elements to skip - could be written in linear iterative style or continuation passing style too

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]


function composition with Array.prototype.filter

uses the highly practical built-in Array.prototype.filter but returns the opposite result using function composition with 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]


linear iterative with in-place mutation

all methods I implemented above do not mutate the original data - in some cases, if you had a particularly large array and you did not want to create a copy with odd values removed, you might wish to perform an in-place modification of data

this answer addresses the issues in your original code

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]

这篇关于删除数组中的奇数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆