【问题标题】:Loop through array when removing elements删除元素时遍历数组
【发布时间】:2013-06-23 13:25:14
【问题描述】:

我想知道在循环内迭代长度在变化的数组是否以及什么是可靠和/或标准的方法。我问是因为每次我想这样做时我最终都会选择不同的方法来执行此操作,例如

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

或

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

这些是我发现自己这样做的方式,但我很好奇是否有标准方法。

【问题讨论】:

  • 你检查过这个[stackoverflow.com/questions/9882284/…答案吗?
  • 您可以在第一个示例中保留您的前向迭代,并将您的帖子递减 i 直接放在 .splice() 调用中:myarray.splice(i--, 1);

标签: javascript arrays loops


【解决方案1】:

我发现在另一个方向迭代更简单:

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

这样你在移除时不必改变增量。

许多开发人员,尤其是那些在 JavaScript 之前不处理类 C 语言的开发人员,发现处理递减运算符的微妙之处令人困惑。我写的循环也可以写成

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

【讨论】:

  • +1 我今天早上在接受采访时问了一个类似的问题 ;-) 最好的部分是我什至没有想到这个解决方案
  • 这绝对是推荐的方法来遍历将删除项目的集合。我用任何语言做这个。
  • @jlafay 我已经取消了你的编辑,因为for (var i = myarray.length; i &gt; 0; i--) 没有做同样的事情(它从数组外部开始并错过索引 0 处的元素)。
  • 您在这两点上都是正确的,但这也意味着您将 i 设置为 myarray.length 的代码也是错误的。那应该是var i = myarray.length - 1。 IMO 在 for 条件中减少索引有点脏,这就是我改变它的原因。我应该检查i &gt;= 0。
  • @dystroy 我很好奇为什么 i--> 0 不会错过索引 0 处的元素,因为看起来 0 > 0 会返回 false?
【解决方案2】:

无论您选择如何做,倒数开始倒计时是最简单的。它还取决于您的数组是否稀疏以及您是否希望它保持稀疏。最简单的方法是为自己创建一个可重用的函数和自己的库。你可以这样做。如果您将compress 设置为true,那么您的数组将变为连续数组而不是稀疏数组。此函数将删除所有匹配的值,并返回一个包含已删除元素的数组。

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

输出

[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] 

开启jsfiddle

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-05
    • 2012-01-13
    • 2013-07-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多