根据对象属性删除数组元素

436

我有一个像这样的对象数组:

var myArray = [
    {field: 'id', operator: 'eq', value: id}, 
    {field: 'cStatus', operator: 'eq', value: cStatus}, 
    {field: 'money', operator: 'eq', value: money}
];

我如何根据属性删除特定的数组对象? 例如,我如何删除字段属性为“money”的数组对象?
12个回答

590

一个可能性:

myArray = myArray.filter(function( obj ) {
    return obj.field !== 'money';
});
请注意,filter创建一个新数组。尽管您使用新引用更新原始变量myArray,但任何其他引用原始数组的变量都不会获得过滤后的数据。请谨慎使用。

7
请注意,filter() 仅适用于Internet Explorer 9+。 - jessegavin
@jessegavin 确实。我应该提到有很多好的 es5 shim 库可用,它们模仿了这些功能(以防您想支持旧版浏览器)。 - jAndy
8
filter()方法创建一个新的数组,如果你能够重新分配变量并且知道没有其他代码区域引用它,那么这很好。但是,如果你需要修改原始数组对象,则无法使用该方法。 - Brian Glick
2
如果数组是树形结构,例如 beforeDeleteOperationArray=[ { "id": 3.1, "name": "test 3.1", "activityDetails": [ { "id": 22, "name": "test 3.1" }, { "id": 23, "name": "changed test 23" } ] } ] 而我想删除 id:23,该怎么办? - forgottofly
No @JackTheKnife - forgottofly
显示剩余3条评论

109

遍历数组,使用splice删除不需要的元素。为了更方便的操作,倒序遍历数组,这样您就不必考虑数组的动态变化:

for (var i = myArray.length - 1; i >= 0; --i) {
    if (myArray[i].field == "money") {
        myArray.splice(i,1);
    }
}

3
"数组的生动性"是什么意思?@Neit the Dark Absol - sisimh
45
他的意思是,如果你通过使用数组的长度作为迭代逻辑的一部分来正向迭代数组,并且由于添加或删除元素而导致数组长度发生变化,你可能会越过数组的末尾或未对数组中的每个项执行操作。反向迭代则更不可能发生这种情况,因为它朝着一个静态的0索引进行工作,而不是一个移动的长度。 - Klors
2
如果数组是树形结构,如下所示beforeDeleteOperationArray=[{ "id": 3.1, "name": "test 3.1", "activityDetails": [ { "id": 22, "name": "test 3.1" }, { "id": 23, "name": "changed test 23" } ] }],我想删除id为23的数据。 - forgottofly
有点显而易见,但如果您只希望删除单个唯一元素,则可以在“if”语句中加入一个break以提高性能,这样循环就不会无谓地遍历数组的其余部分。 - Patrick Borkowicz
@Satyadev 请阅读那个问题上被接受的答案。 - Niet the Dark Absol
显示剩余5条评论

106

假设您想根据其字段属性删除第二个对象。

使用 ES6,只需这样即可。

myArray.splice(myArray.findIndex(item => item.field === "cStatus"), 1)

8
我尝试了这个代码,但是它没有从OP的数组中“移除”第三个项目,而是“过滤掉”并仅显示第三个项目。 - Compaq LE2202x
13
两年后,对于您来说可能已经很明显了,但对于未来的开发者而言:splice 会改变原始数组,所以你得到的值是被移除的那个元素,但如果你接下来查看 myArray,该项将会消失。 - David Mulder
8
如果 findIndex 没有找到元素,则返回 -1,并且使用 splice 删除最后一个元素,即使它与谓词不匹配。 - Yannic

65

在ES6中,只需要一行代码。

const arr = arr.filter(item => item.key !== "some value");

:)


6
请记住,过滤器会创建一个新的数组。 - Kurt Van den Branden

26
您可以使用 Lodash 的 findIndex 方法获取特定元素的索引,然后使用 splice 进行删除。
myArray.splice(_.findIndex(myArray, function(item) {
    return item.value === 'money';
}), 1);

更新

你也可以使用ES6的findIndex()方法。

findIndex() 方法返回数组中满足提供的测试函数的第一个元素的索引。否则返回 -1。

const itemToRemoveIndex = myArray.findIndex(function(item) {
  return item.field === 'money';
});

// proceed to remove an item only if it exists.
if(itemToRemoveIndex !== -1){
  myArray.splice(itemToRemoveIndex, 1);
}

数组是一种树形结构吗? - forgottofly
@forgottofly 树形结构?我认为这里的 myArray 是一个对象数组。 - Sridhar
4
如果这个数组是一棵树形结构,变量名为beforeDeleteOperationArray=[ { "id": 3.1, "name": "test 3.1", "activityDetails": [ { "id": 22, "name": "test 3.1" }, { "id": 23, "name": "changed test 23" } ] } ],我想要删除id为23的数据。 - forgottofly
2
如果在ES6版本的findIndex中未找到元素,则返回-1,并且splice将删除最后一个元素,即使它与谓词不匹配。 - Yannic
1
@Yannic 很好的发现。感谢指出。我已经更新了我的答案。 - Sridhar
可能也可以使用三元运算符来实现,以保持单行代码并避免创建额外的变量。 - undefined

17
我们可以使用以下两种方法基于属性来移除元素。
  1. 使用过滤器方法
testArray.filter(prop => prop.key !== 'Test Value')
  1. 使用splice方法。对于这种方法,我们需要找到属性的索引。
const index = testArray.findIndex(prop => prop.key === 'Test Value')
testArray.splice(index,1)

数组的 filter() 函数不会修改原始数组,因此您的代码需要一个 let newArray = testArray.filter(prop => prop.key !== 'Test Value')。 - Peter Utekal

9

使用jQuery grep还有另一种选择。将true作为第三个参数传递以确保grep删除与您的函数匹配的项。

users = $.grep(users, function(el, idx) {return el.field == "money"}, true)

如果您已经在使用jQuery,则不需要使用shim,这可能比使用Array.filter更有用。


3
var myArray = [
    {field: 'id', operator: 'eq', value: id}, 
    {field: 'cStatus', operator: 'eq', value: cStatus}, 
    {field: 'money', operator: 'eq', value: money}
];
console.log(myArray.length); //3
myArray = $.grep(myArray, function(element, index){return element.field == "money"}, true);
console.log(myArray.length); //2

元素是数组中的一个对象。第三个参数true表示将返回一个不符合函数逻辑的元素数组,false表示将返回一个符合函数逻辑的元素数组。


2
使用 lodash 库:

var myArray = [
    {field: 'id', operator: 'eq', value: 'id'}, 
    {field: 'cStatus', operator: 'eq', value: 'cStatus'}, 
    {field: 'money', operator: 'eq', value: 'money'}
];
var newArray = _.remove(myArray, function(n) {
  return n.value === 'money';;
});
console.log('Array');
console.log(myArray);
console.log('New Array');
console.log(newArray);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.js"></script>


2

根据上面的评论,以下是根据键名和键值删除对象的代码:

 var items = [ 
  { "id": 3.1, "name": "test 3.1"}, 
  { "id": 22, "name": "test 3.1" }, 
  { "id": 23, "name": "changed test 23" } 
  ]

    function removeByKey(array, params){
      array.some(function(item, index) {
        return (array[index][params.key] === params.value) ? !!(array.splice(index, 1)) : false;
      });
      return array;
    }

    var removed = removeByKey(items, {
      key: 'id',
      value: 23
    });

    console.log(removed);

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