admin管理员组

文章数量:1279182

I am trying to e up with another way to remove all of the odd numbers from an array. A friend was able to e 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);

I am trying to e up with another way to remove all of the odd numbers from an array. A friend was able to e 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);
Share Improve this question asked Mar 31, 2017 at 3:20 bemonbemon 1234 silver badges15 bronze badges 1
  • 1 "another solution" - There are lots of possible solutions, but I doubt you can find anything simpler than .filter(). By the way, the solution shown may work, but it doesn't make much sense: the outer loop will run through to the original array length even after items are removed, and the inner loop always restarts with the first element so you're reprocessing elements for no reason. (And it is a terrible variable name.) – nnnnnn Commented Mar 31, 2017 at 3:25
Add a ment  | 

3 Answers 3

Reset to default 8

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

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

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 acmodate 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 position with Array.prototype.filter

uses the highly practical built-in Array.prototype.filter but returns the opposite result using function position with not

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

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

const not = x => !x

const reject = (f, xs) =>
  xs.filter(p(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]

If you only need support as far back as IE9 you can use the Array.prototype.filter method.

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

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

Output will be a new array of the filtered values (Only even).

本文标签: javascriptRemove odd numbers in arrayStack Overflow