javascript 按对象属性从数组中删除对象

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16491758/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 04:54:40  来源:igfitidea点击:

remove objects from array by object property

javascript

提问by Dan Kanze

var listToDelete = ['abc', 'efg'];

var arrayOfObjects = [{id:'abc',name:'oh'}, // delete me
                      {id:'efg',name:'em'}, // delete me
                      {id:'hij',name:'ge'}] // all that should remain

How do I remove an object from the array by matching object property?

如何通过匹配对象属性从数组中删除对象?

Only native JavaScript please.

请只使用原生 JavaScript。

I am having trouble using splice because length diminishes with each deletion. Using clone and splicing on orignal index still leaves you with the problem of diminishing length.

我在使用 splice 时遇到问题,因为每次删除时长度都会减少。在原始索引上使用克隆和拼接仍然会给您带来长度减少的问题。

回答by Ry-

I assume you used splicesomething like this?

我假设你用过splice这样的东西?

for (var i = 0; i < arrayOfObjects.length; i++) {
    var obj = arrayOfObjects[i];

    if (listToDelete.indexOf(obj.id) !== -1) {
        arrayOfObjects.splice(i, 1);
    }
}

All you need to do to fix the bug is decrement ifor the next time around, then (and looping backwards is also an option):

修复错误所需要做的就是i在下一次递减,然后(向后循环也是一种选择):

for (var i = 0; i < arrayOfObjects.length; i++) {
    var obj = arrayOfObjects[i];

    if (listToDelete.indexOf(obj.id) !== -1) {
        arrayOfObjects.splice(i, 1);
        i--;
    }
}

To avoid linear-time deletions, you can write array elements you want to keepover the array:

为了避免线性时间删除,您可以编写要保留在数组上的数组元素:

var end = 0;

for (var i = 0; i < arrayOfObjects.length; i++) {
    var obj = arrayOfObjects[i];

    if (listToDelete.indexOf(obj.id) === -1) {
        arrayOfObjects[end++] = obj;
    }
}

arrayOfObjects.length = end;

and to avoid linear-time lookups in a modern runtime, you can use a hash set:

为了避免现代运行时中的线性时间查找,您可以使用哈希集:

const setToDelete = new Set(listToDelete);
let end = 0;

for (let i = 0; i < arrayOfObjects.length; i++) {
    const obj = arrayOfObjects[i];

    if (setToDelete.has(obj.id)) {
        arrayOfObjects[end++] = obj;
    }
}

arrayOfObjects.length = end;

which can be wrapped up in a nice function:

它可以包含在一个很好的函数中:

const filterInPlace = (array, predicate) => {
    let end = 0;

    for (let i = 0; i < array.length; i++) {
        const obj = array[i];

        if (predicate(obj)) {
            array[end++] = obj;
        }
    }

    array.length = end;
};

const toDelete = new Set(['abc', 'efg']);

const arrayOfObjects = [{id: 'abc', name: 'oh'},
                        {id: 'efg', name: 'em'},
                        {id: 'hij', name: 'ge'}];

filterInPlace(arrayOfObjects, obj => !toDelete.has(obj.id));
console.log(arrayOfObjects);

If you don't need to do it in place, that's Array#filter:

如果你不需要就地做,那就是Array#filter

const toDelete = new Set(['abc', 'efg']);
const newArray = arrayOfObjects.filter(obj => !toDelete.has(obj.id));

回答by parliament

You can remove an item by one of its properties without using any 3rd party libs like this:

您可以通过其属性之一删除项目,而无需使用任何 3rd 方库,如下所示:

var removeIndex = array.map(function(item) { return item.id; })
                       .indexOf("abc");

~removeIndex && array.splice(removeIndex, 1);

回答by Rahul R.

With lodash/underscore:

使用 lodash/下划线:

If you want to modify the existing array itself, then we have to use splice. Here is the little better/readable way using findWhereof underscore/lodash:

如果要修改现有数组本身,则必须使用splice。这是使用下划线/lodash 的findWhere的更好/可读的方法:

var items= [{id:'abc',name:'oh'}, // delete me
                  {id:'efg',name:'em'},
                  {id:'hij',name:'ge'}];

items.splice(_.indexOf(items, _.findWhere(items, { id : "abc"})), 1);

With ES5 or higher

使用 ES5 或更高版本

(without lodash/underscore)

没有lodash/下划线

With ES5 onwards we have findIndexmethod on array, so its easy without lodash/underscore

从 ES5 开始,我们findIndex在数组上有方法,所以没有 lodash/underscore 很容易

items.splice(items.findIndex(function(i){
    return i.id === "abc";
}), 1);

(ES5 is supported in almost all morden browsers)

(几乎所有现代浏览器都支持 ES5)

About findIndex, and its Browser compatibility

关于 findIndex及其浏览器兼容性

回答by fatlinesofcode

findIndex works for modern browsers:

findIndex 适用于现代浏览器:

var myArr = [{id:'a'},{id:'myid'},{id:'c'}];
var index = arr.findIndex(function(o){
     return o.id === 'myid';
})
if (index !== -1) myArr.splice(index, 1);

回答by Naresh Chennuri

To delete an object by it's id in given array;

根据给定数组中的 id 删除对象;

const hero = [{'id' : 1, 'name' : 'hero1'}, {'id': 2, 'name' : 'hero2'}];
//remove hero1
const updatedHero = hero.filter(item => item.id !== 1);

回答by user2704940

If you just want to remove it from the existing array and not create a new one, try:

如果您只想从现有数组中删除它而不是创建一个新数组,请尝试:

var items = [{Id: 1},{Id: 2},{Id: 3}];
items.splice(_.indexOf(items, _.find(items, function (item) { return item.Id === 2; })), 1);

回答by Felix Rabe

Loop in reverse by decrementing ito avoid the problem:

通过递减i来反向循环以避免问题:

for (var i = arrayOfObjects.length - 1; i >= 0; i--) {
    var obj = arrayOfObjects[i];

    if (listToDelete.indexOf(obj.id) !== -1) {
        arrayOfObjects.splice(i, 1);
    }
}

Or use filter:

或使用filter

var newArray = arrayOfObjects.filter(function(obj) {
    return listToDelete.indexOf(obj.id) === -1;
});

回答by Sylvain Leroux

Only native JavaScript please.

请只使用原生 JavaScript。

As an alternative, more "functional" solution, working on ECMAScript 5, you could use:

作为替代的、更“功能性”的解决方案,在 ECMAScript 5 上工作,您可以使用:

var listToDelete = ['abc', 'efg'];
var arrayOfObjects = [{id:'abc',name:'oh'}, // delete me
                      {id:'efg',name:'em'}, // delete me
                      {id:'hij',name:'ge'}]; // all that should remain

arrayOfObjects.reduceRight(function(acc, obj, idx) {
    if (listToDelete.indexOf(obj.id) > -1)
        arrayOfObjects.splice(idx,1);
}, 0); // initial value set to avoid issues with the first item and
       // when the array is empty.

console.log(arrayOfObjects);
[ { id: 'hij', name: 'ge' } ]

According to the definition of 'Array.prototype.reduceRight' in ECMA-262:

根据ECMA-262 中 'Array.prototype.reduceRight' 的定义

reduceRight does not directly mutate the object on which it is called but the object may be mutated by the calls to callbackfn.

reduceRight 不会直接改变调用它的对象,但该对象可能会通过调用 callbackfn 来改变

So this is a valid usage of reduceRight.

所以这是reduceRight.

回答by Miroslav Savovski

Check this out using Set and ES6 filter.

使用 Set 和 ES6 过滤器检查一下。

  let result = arrayOfObjects.filter( el => (-1 == listToDelete.indexOf(el.id)) );
  console.log(result);

Here is JsFiddle: https://jsfiddle.net/jsq0a0p1/1/

这是 JsFiddle:https://jsfiddle.net/jsq0a0p1/1/

回答by Subhojit Mondal

var arrayOfObjects = [{id:'abc',name:'oh'}, // delete me
                      {id:'efg',name:'em'}, // delete me
                      {id:'hij',name:'ge'}] // all that should remain

as per your answer will be like this. when you click some particular object send the index in the param for the delete me function. This simple code will work like charm.

根据你的回答会是这样的。当您单击某个特定对象时,请发送参数中的索引以用于删除我的功能。这个简单的代码会像魅力一样工作。

function deleteme(i){
    if (i > -1) {
      arrayOfObjects.splice(i, 1);
    }
}