在JavaScript中,根据关键值查找和删除数组中的对象

224
我一直在尝试几种方法来查找一个数组中ID=var的对象,如果找到,则从数组中移除该对象并返回新的对象数组。

数据:

[
    {"id":"88","name":"Lets go testing"},
    {"id":"99","name":"Have fun boys and girls"},
    {"id":"108","name":"You are awesome!"}
]

我可以使用jQuery $grep搜索数组;

var id = 88;

var result = $.grep(data, function(e){
     return e.id == id;
});

但是当id == 88时,我该如何删除整个对象,并返回以下数据?

Data:

[
    {"id":"99", "name":"Have fun boys and girls"},
    {"id":"108", "name":"You are awesome!"}
]

使用 slice 函数和一个小的 for 循环怎么样? - Ahmed Hamdy
1
当然可以,但我写这个问题的原因是因为我卡住了 ;) 有什么代码片段吗? - Tom
请查看此帖子:https://dev59.com/w2TWa4cB1Zd3GeqPDXAd - Ahmed Hamdy
标题和问题文本似乎存在冲突...表明两种完全不同的方法:A. 从数组中删除项目与 B. 创建一个新的、过滤后的数组。 - canon
这个回答解决了你的问题吗?根据对象属性删除数组元素 - Heretic Monkey
14个回答

294

如果您没有使用jQuery,这是一种解决方案:

myArray = myArray.filter(function( obj ) {
  return obj.id !== id;
});

3
在父数组上执行findIndex()splice(index, 1),这种方式好还是本方法更好? - Alex
splice会改变原始数组,而使用filter则可以选择。 - velop
34
使用以下代码可以将其简化为一行:myArr = myArray.filter(obj => obj.id !== id); 这行代码的作用是过滤数组中id不等于指定值的元素,返回新的数组。 - DBrown
18
更加简洁的翻译:arr = arr.filter(obj => obj.id !== id); - Omar
应该是被接受的本地答案!谢谢。 - BenjaminK
1
有人能解释一下“filter()”和“findIndex()+splice(index,1)”之间的时间复杂度差异吗? - Naman Dutta

171

我可以使用grep函数在数组中查找id,但是如何删除整个id等于88的对象?

只需通过相反的谓词进行过滤:

var data = $.grep(data, function(e){ 
     return e.id != id; 
});

13
这个答案提供了jQuery最简明和惯用的解决方案。 - Bryan
1
在您想要删除所有ID为something的项目的情况下是可以的...但是当使用$.grep时要小心,因为它会搜索整个数组,对于长数组来说效率不高。有时您只需要检查给定ID是否存在于数组中,那么最好使用另一种迭代方法 ;) - julianox
1
这并不会将该对象从列表中移除。 - Arun Sivan
1
@ArunSivan slice 也不会删除任何内容。不确定你的意思是什么。如果您自己有特定的问题,您可能需要提出新问题 - Bergi
1
@学习者 data.filter(e => !ids.includes(e.id)) - Bergi
显示剩余6条评论

107

您可以简化此操作,这里真的没有必要使用jQuery。

var id = 88;

for(var i = 0; i < data.length; i++) {
    if(data[i].id == id) {
        data.splice(i, 1);
        break;
    }
}

只需遍历列表,找到匹配的ID,使用splice函数删除元素并使用break语句退出循环。


20
+1,但是你应该提到这只会删除第一个匹配的项。 - Bergi
9
如果您需要删除每个匹配项,请使用i=data.length; i > 0; i--的反向循环,并且不要使用break - Jeremy Belolo
5
i = data.length will break any data[i], it should be something like i=data.length -1 ; i > -1; i-- - distante

43

使用 ES6/2015 中的 findIndex 方法和数组展开操作符,有一种新的方法可以实现这个功能:

const index = data.findIndex(obj => obj.id === id);
const newData = [
    ...data.slice(0, index),
    ...data.slice(index + 1)
]

您可以像这样将其转换为函数,以便稍后重复使用:

function remove(array, key, value) {
    const index = array.findIndex(obj => obj[key] === value);
    return index >= 0 ? [
        ...array.slice(0, index),
        ...array.slice(index + 1)
    ] : array;
}

这样,您可以使用一个方法通过不同的键删除项目(如果没有符合条件的对象,则返回原始数组):

const newData = remove(data, "id", "88");
const newData2 = remove(data, "name", "You are awesome!");

或者你可以将它放在你的Array.prototype上:

Array.prototype.remove = function (key, value) {
    const index = this.findIndex(obj => obj[key] === value);
    return index >= 0 ? [
        ...this.slice(0, index),
        ...this.slice(index + 1)
    ] : this;
};

并且这样使用:

const newData = data.remove("id", "88");
const newData2 = data.remove("name", "You are awesome!");

findIndex() 真的很棒! - danielcraigie
如果你有多个键和值怎么办? - QMaster

13

本地ES6解决方案:

const pos = data.findIndex(el => el.id === ID_TO_REMOVE);
if (pos >= 0)
    data.splice(pos, 1);

如果您确定元素在数组中存在:

data.splice(data.findIndex(el => el.id === ID_TO_REMOVE), 1);

原型:

Array.prototype.removeByProp = function(prop,val) {
    const pos = this.findIndex(x => x[prop] === val);
    if (pos >= 0)
        return this.splice(pos, 1);
};

// usage:
ar.removeByProp('id', ID_TO_REMOVE);

http://jsfiddle.net/oriadam/72kgprw5/

注意:此操作会就地删除项目。如果您需要一个新数组,请使用前面答案中提到的filter方法。


1
你没有处理 id 未找到的情况。在这种情况下,你的解决方案会移除数组元素。 - tzi
这很干净。 - Pablo Fernandez

12
var items = [
  {"id":"88","name":"Lets go testing"},
  {"id":"99","name":"Have fun boys and girls"},
  {"id":"108","name":"You are awesome!"}
];
如果您正在使用jQuery,请像这样使用jQuery.grep:jQuery.grep
items = $.grep(items, function(item) { 
  return item.id !== '88';
});
// items => [{ id: "99" }, { id: "108" }]

使用ES5的Array.prototype.filter方法:

items = items.filter(function(item) { 
  return item.id !== '88'; 
});
// items => [{ id: "99" }, { id: "108" }]

1
不要使用 jQuery 的 map 作为过滤器。 - Bergi
1
同意!你使用grep和jQuery的解决方案是正确的。 - nekman

9
假设id是唯一的,你只需要删除一个元素,splice就可以解决问题:
var data = [
  {"id":"88","name":"Lets go testing"},
  {"id":"99","name":"Have fun boys and girls"},
  {"id":"108","name":"You are awesome!"}
],
id = 88;

console.table(data);

$.each(data, function(i, el){
  if (this.id == id){
    data.splice(i, 1);
  }
});

console.table(data);

你的回调函数中元素的顺序是反过来的。应该是each(data,function(idx,ele)。我稍后会向你收取我浪费在这上面的30分钟的费用 :) - CSharper
哎呀,既然这样,我能做的最少就是更新我的答案。我为你浪费的30分钟感到非常抱歉。 - James Hibbard

6
const data = [
    {"id":"88","name":"Lets go testing"},
    {"id":"99","name":"Have fun boys and girls"},
    {"id":"108","name":"You are awesome!"}
];

这里我们获取id值为"88"的对象的索引

const index = data.findIndex(item => item.id === "88");
console.log(index); // 0

我们使用splice函数从数据数组中删除指定的对象。
data.splice(index,1);
console.log(data); // [{"id":"99","name":"Have fun boys and girls"},{"id":"108","name":"You are awesome!"}]

6

我同意之前的答案。如果你想通过id查找并删除一个对象,可以使用以下简单代码:

var obj = JSON.parse(data);
var newObj = obj.filter(item => item.Id != 88);

4
也许您正在寻找$. grep()函数:
arr = [
  {"id":"88","name":"Lets go testing"},
  {"id":"99","name":"Have fun boys and girls"},
  {"id":"108","name":"You are awesome!"}
];

id = 88;
arr = $.grep(arr, function(data, index) {
   return data.id != id
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接