最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Loop through array when removing elements - Stack Overflow

programmeradmin5浏览0评论

I'm wondering if and what is a reliable and/or standard way of iterating an array whose length is changing inside the loop. I ask because I end up choosing a different method to do this each time I want to do it, e.g.

for ( var i = 0; i < myarray.length; i++ ) {
  if (myarray[i] === 'something') {
    myarray.splice(i, 1);

    // *to avoid jumping over an element whose index was just shifted back to the current i
    i--;
  }
}

or

var i = 0;
while (myarray[i]) {
  if (myarray[i] === 'something') {
    myarray.splice(i, 1);
  } else {
    i++;
  }
}

These are the ways I find myself doing this, but I'm curious if there is a standard approach.

I'm wondering if and what is a reliable and/or standard way of iterating an array whose length is changing inside the loop. I ask because I end up choosing a different method to do this each time I want to do it, e.g.

for ( var i = 0; i < myarray.length; i++ ) {
  if (myarray[i] === 'something') {
    myarray.splice(i, 1);

    // *to avoid jumping over an element whose index was just shifted back to the current i
    i--;
  }
}

or

var i = 0;
while (myarray[i]) {
  if (myarray[i] === 'something') {
    myarray.splice(i, 1);
  } else {
    i++;
  }
}

These are the ways I find myself doing this, but I'm curious if there is a standard approach.

Share Improve this question asked Jun 26, 2013 at 12:04 rob-gordonrob-gordon 1,4884 gold badges22 silver badges40 bronze badges 2
  • Have you checked this [stackoverflow.com/questions/9882284/… answer? – Rui Marques Commented Jun 26, 2013 at 12:07
  • 1 You could keep your forward iteration in the first example and put your post decrementing i directly in the .splice() call: myarray.splice(i--, 1); – user2437417 Commented Jun 26, 2013 at 12:16
Add a comment  | 

2 Answers 2

Reset to default 23

I find simpler to iterate in the other direction :

for (var i=myarray.length; i--; ) {
   if (myarray[i] === 'something') myarray.splice(i, 1);
}

This way you don't have to change the increment when removing.

Many developers, especially the ones who didn't deal with C-like languages before JavaScript, find it confusing to deal with the subtleties of the decrement operator. The loop I wrote can also be written as

for (var i=myarray.length-1; i>=0; i--) {

However you choose to do it, starting in reverse and counting down is simplest. It also depends on whether your array is sparse and if you wish for it to remain sparse. Easiest is to create yourself a reusable function and your own library. You could do this. If you set compress to true then your array will become a continuous rather than sparse array. This function will remove all matched occurrences of the value and will return an array of the removed elements.

Javascript

function is(x, y) {
    if (x === y) {
        if (x === 0) {
            return 1 / x === 1 / y;
        }

        return true;
    }

    var x1 = x,
        y1 = y;

    return x !== x1 && y !== y1;
}

function removeMatching(array, value /*, compress (default = false)*/ ) {
    var removed = [],
        compress = arguments[2],
        index,
        temp,
        length;

    if (typeof compress !== "boolean") {
        compress = false;
    }

    if (compress) {
        temp = [];
        length = array.length;
        index = 0;
        while (index < length) {
            if (array.hasOwnProperty(index)) {
                temp.push(array[index]);
            }

            index += 1;
        }
    } else {
        temp = array;
    }

    index = 0;
    length = temp.length;
    while (index < length) {
        if (temp.hasOwnProperty(index) && is(temp[index], value)) {
            if (compress) {
                removed.push(temp.splice(index, 1)[0]);
            } else {
                removed.push(temp[index]);
                delete temp[index];
            }
        }

        index += 1;
    }

    if (compress) {
        array.length = 0;
        index = 0;
        length = temp.length;
        while (index < length) {
            if (temp.hasOwnProperty(index)) {
                array.push(temp[index]);
            }

            index += 1;
        }
    }

    return removed;
}

var test = [];

test[1] = 1;
test[50] = 2;
test[100] = NaN;
test[101] = NaN;
test[102] = NaN;
test[200] = null;
test[300] = undefined;
test[400] = Infinity;
test[450] = NaN;
test[500] = -Infinity;
test[1000] = 3;

console.log(test);
console.log(removeMatching(test, NaN));
console.log(test);
console.log(removeMatching(test, Infinity, true));
console.log(test);

Output

[1: 1, 50: 2, 100: NaN, 101: NaN, 102: NaN, 200: null, 300: undefined, 400: Infinity, 450: NaN, 500: -Infinity, 1000: 3]
[NaN, NaN, NaN, NaN]
[1: 1, 50: 2, 200: null, 300: undefined, 400: Infinity, 500: -Infinity, 1000: 3]
[Infinity]
[1, 2, null, undefined, -Infinity, 3] 

On jsfiddle

发布评论

评论列表(0)

  1. 暂无评论