【问题标题】:Javascript splice is breaking on jQuery .each()?Javascript 拼接在 jQuery .each() 上中断?
【发布时间】:2012-02-24 17:11:38
【问题描述】:
var results = ['one', 'two', 'one hundred', 'three'];
var removal = [];
$.each(results, function(i) {
    removal.push(i);
    if (results[i].indexOf('one') == -1){
        console.log('Removing:' + results[i] + '(' + removal[i] + ')');
        results = results.splice(removal[i], 1);
    }
});

我有以下代码,但在删除第一个结果后它会中断。

我希望它删除任何不包含“一”字的内容。

我猜它正在中断,因为移除顺序一旦被移除就会改变。

我做错了什么?

【问题讨论】:

  • 上面的代码实际上应该做什么?假设您按照以下答案解决了$.each() 循环的问题,您仍然将数组indexes 推入removal 数组,因此当循环结束时removal[0,1,2,3]。您是否打算将 推送到 removal 中?此外,您在 if 测试之前将它们推入,因此removal 实际上并没有跟踪删除的内容。在您的if 中,您使用i 作为removalresults 的索引,即使这些数组的长度不同,因为您要向removal 添加元素并从results 中删除元素。

标签: javascript jquery


【解决方案1】:

在使用$.each() 迭代数组时,不应拼接数组。

由于您要更改数组的长度,因此您将超出最终索引。

只需使用for 循环并在删除项目时调整i...

var results = ['one', 'two', 'one hundred', 'three'];
var removal = [];
for(var i = 0; i < results.length; i++) {
    removal.push(i);
    if (results[i].indexOf('one') == -1){
        console.log('Removing:' + results[i] + '(' + removal[i] + ')');
        results.splice(i, 1);
        i--;
    }
};

请注意,我更改了这个...

results = results.splice(removal[i], 1);

到这个...

results.splice(removal[i], 1);

您不希望这样,因为 splice() 修改了原始内容,并返回删除的项目。

【讨论】:

  • @user1088771:请注意,我刚刚更新了代码。我没有注意到您使用的是 results.splice(removal[i], 1); 而不是 results.splice(i, 1);
  • 根据我刚刚在问题下留下的评论,如果您更仔细地查看代码,您会发现removal[i] 的值实际上是i。也就是说,indexes 被推入数组而不是 values
  • @nnnnnn:是的,我注意到了。原始代码使用该数组来获取.splice() 的索引。我不知道为什么要这样做,但代码有几处错误,所以我认为大部分是基于误解。
【解决方案2】:
var myArr = [0,1,2,3,4,5,6];

问题陈述:

myArr.splice(2,1);

  \\ [0, 1, 3, 4, 5, 6];

现在在第二个位置移动 3 次,长度减少 1,这会产生问题。

解决方案:一个简单的解决方案是在拼接时反向迭代。

var i = myArr.length;
while (i--) {
    console.log(myArr);
    myArr.splice(i,1);
}

输出:

[0, 1, 2, 3, 4, 5, 6]
[0, 1, 2, 3, 4, 5]
[0, 1, 2, 3, 4]
[0, 1, 2, 3]
[0, 1, 2]
[0, 1]
[0]

【讨论】:

  • 谢谢,这确实是通过 while 函数向后迭代的最干净的解决方案。
【解决方案3】:

问题在于$.each() 函数从第一个元素开始按顺序遍历数组,并在内部设置它将在开始时使用的索引范围。因此,当您从该数组中删除项目时,它并不知道您已经这样做了。

您可以使用标准的for 语句轻松解决此问题。如果从列表的末尾向后循环到开头,则可以删除项目而不会影响循环。如果向前循环,则每次从数组中删除项目时都需要调整循环计数器。

【讨论】:

    【解决方案4】:

    是的,在循环时修改数组结构会造成大量破坏。尝试使用临时数组:

    var results = ['one', 'two', 'one hundred', 'three'];
    var removal = [];
    var newResults = [];
    $.each(results, function(i) {
        removal.push(i);
        if (results[i].indexOf('one') > -1){
            newResults.push(i);
        } else {
            console.log('Removing:' + results[i] + '(' + removal[i] + ')');
        }
    });
    results = newResults;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-12-24
      • 1970-01-01
      • 1970-01-01
      • 2017-11-20
      • 2011-01-01
      • 1970-01-01
      • 2015-05-18
      • 1970-01-01
      相关资源
      最近更新 更多