我想删除一个带有多个函数的数组中的元素。
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
当循环重复两次时,该循环不会删除该元素,只删除其中一个元素。
为什么?
答案 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)
创建给定数组的集合,原始数组未修改
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);
}