循环以删除多次出现的数组中的元素

时间:2013-12-22 19:31:39

标签: javascript arrays

我想删除一个带有多个函数的数组中的元素。

var array=["hello","hello","world",1,"world"];

function removeItem(item){
    for(i in array){
        if(array[i]==item) array.splice(i,1);
    }
}
removeItem("world");
//Return hello,hello,1
removeItem("hello");
//Return hello,world,1,world

当循环重复两次时,该循环不会删除该元素,只删除其中一个元素。

为什么?

10 个答案:

答案 0 :(得分:32)

你有一个名为filter的内置函数,它根据谓词(条件)过滤数组。

它不会改变原始数组,但会返回一个新的过滤数组。

var array=["hello","hello","world",1,"world"];
var filtered = array.filter(function(element) {
    return element !== "hello";
}); // filtered contains no occurrences of hello

您可以将其提取到一个函数:

function without(array, what){
    return array.filter(function(element){ 
        return element !== what;
    });
}

然而,原始过滤器似乎足够表达。

Here is a link to its documentation

您的原始功能存在一些问题:

  • 它使用for... in循环迭代数组,该循环无法保证迭代顺序。另外,don't use it to iterate through arrays - 更喜欢普通for...循环或.forEach
  • 你正在使用一个一个错误来迭代一个数组,所以你要跳过下一个项目,因为你要删除元素并继续运行数组。

答案 1 :(得分:8)

这是因为for - 循环在删除事件后转到下一个项目,因此在该项目之后直接跳过该项目。

例如,假设需要在此数组中删除item1(请注意<-是循环的索引):

item1 (<-), item2, item3

删除后:

item2 (<-), item3

并且在索引更新后(循环结束)

item2, item3 (<-)

所以你可以看到item2被跳过,因此没有被检查!

因此,您需要通过手动将索引减1来补偿这一点,如下所示:

function removeItem(item){
    for(var i = 0; i < array.length; i++){
        if(array[i]==item) {
            array.splice(i,1);
            i--; // Prevent skipping an item
        }
    }
}

而不是使用此for - 循环,您可以使用更“现代”的方法来filter other answer by Benjamin {{3}}中显示不需要的内容。

答案 2 :(得分:1)

这些答案都不是最优的。过滤器接受的答案将导致数组的新实例。获得第二多选票的答案,即在每次拼接中退一步的for循环,都是不必要的复杂。

如果你想进行for循环循环,只需向后计数到0。

KClass

但是,我使用了一个令人惊讶的快速方法,使用了while循环和indexOf:

x

使这种方法不重复的原因是,在删除之后,下一次搜索将从删除项后面的下一个元素的索引处开始。这是因为您可以将起始索引作为第二个参数传递给for (var i = array.length - 0; i >= 0; i--) { if (array[i] === item) { array.splice(i, 1); } }

在比较上述两种方法和接受的过滤方法的 jsPerf test case 中,var itemIndex = 0; while ((itemIndex = valuesArray.indexOf(findItem, itemIndex)) > -1) { valuesArray.splice(itemIndex, 1); } 通常在Firefox和Chrome上首先完成,在IE上排名第二。 indexOf方法总是慢得多。

结论:反向for循环是一段时间,indexOf是目前我可以找到的从数组中删除同一元素的多个实例的最佳方法。使用过滤器会创建一个新数组并且速度较慢,所以我会避免这种情况

答案 3 :(得分:1)

在这种情况下,您可以使用loadash或下划线js 如果arr是一个数组,你可以删除重复:

var arr = [2,3,4,4,5,5];

arr = _.uniq(arr);

答案 4 :(得分:0)

尝试“手动”运行代码 - “你好”是彼此追随的。你移除了第一个,你的数组缩小了一个项目,现在你的索引遵循下一个项目。

删除“你好” 开始循环。 i = 0,array = [“hello”,“hello”,“world”,1,“world”]我指的是“你好”     删除第一项,i = 0 array = [“hello”,“world”,1,“world”] next loop,i = 1,array = [“hello”,“world”,1,“world”]。第二个“你好”不会被删除。

让我们看看“世界”= i = 2,指向“世界”(删除)。在下一个循环中,数组是: [“你好”,“你好”,1,“世界”]和i = 3。这是第二个“世界”。

你希望发生什么?要删除该项目的所有实例吗?还是只有第一个?对于第一种情况,删除应该在

while (array[i] == item) array.splice(i,1);

表示第二种情况 - 一旦删除了项目,就立即返回。

答案 5 :(得分:0)

创建给定数组的集合,原始数组未修改

Demo on Fiddle

    var array=["hello","hello","world",1,"world"];

    function removeDups(items) {
        var i,
            setObj = {},
            setArray = [];
        for (i = 0; i < items.length; i += 1) {
            if (!setObj.hasOwnProperty(items[i])) {
                setArray.push(items[i]);
                setObj[items[i]] = true;
            }
        }
        return setArray;
    }

    console.log(removeDups(array)); // ["hello", "world", 1]

答案 6 :(得分:0)

我必须说我的方法没有使用splice功能,你也需要另一个数组用于此解决方案。

首先,我猜你循环数组的方式不正确。您正在使用for in循环,这些循环用于对象,而不是数组。如果您使用的是jQuery,则最好使用$.each;如果您使用的是vanila Javascript,则最好使用Array.prototype.forEach

其次,为什么不创建一个新的空数组,循环遍历它并只向新数组添加唯一元素,如下所示:

第一种方法(jQuery)

 var newArray = [];
 $.each(array, function(i, element) {
        if ($.inArray(element, newArray) === -1) {
            newArray.push(region);
        }
 });

第二种方法(Vanila Javascript)

var newArray = [];
array.forEach(function(i, element) {
  if (newArray.indexOf(element) === -1) {
            newArray.push(region);
  }
});

答案 7 :(得分:0)

我需要稍微改变一下,能够从数组中删除'n'项的出现,所以我将@ Veger的答案修改为:

function removeArrayItemNTimes(arr,toRemove,times){
    times = times || 10;
    for(var i = 0; i < arr.length; i++){
        if(arr[i]==toRemove) {
            arr.splice(i,1);
            i--; // Prevent skipping an item
            times--;
            if (times<=0) break;
        }
    }
    return arr;
}

答案 8 :(得分:0)

另一种方法是对数组进行排序,然后处理值的索引。

function(arr) {
    var sortedArray = arr.sort();
    //In case of numbers, you can use arr.sort(function(a,b) {return a - b;})
    for (var i = 0; sortedArray.length; i++) {
        if (sortedArray.indexOf(sortedArray[i]) === sortedArray.lastIndexOf(sortedArray[i]))
            continue;
        else
            sortedArray.splice(sortedArray.indexOf(sortedArray[i]), (sortedArray.lastIndexOf(sortedArray[i]) - sortedArray.indexOf(sortedArray[i])));
    }
}

答案 9 :(得分:0)

您可以使用以下代码来删除数组val中值arr的多次出现。

while(arr.indexOf(val)!=-1){
  arr.splice(arr.indexOf(val), 1);
}