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

Dan*_*nze 122 javascript

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
Run Code Online (Sandbox Code Playgroud)

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

请使用原生JavaScript.

我在使用拼接时遇到问题,因为每次删除都会缩短长度.在orignal索引上使用克隆和拼接仍然会给你带来缩短长度的问题.

Ry-*_*Ry- 146

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

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

    if (listToDelete.indexOf(obj.id) !== -1) {
        arrayOfObjects.splice(i, 1);
    }
}
Run Code Online (Sandbox Code Playgroud)

你需要做的就是修复这个bug i,下次再减量,然后(向后循环也是一个选项):

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

    if (listToDelete.indexOf(obj.id) !== -1) {
        arrayOfObjects.splice(i, 1);
        i--;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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;
Run Code Online (Sandbox Code Playgroud)

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

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;
Run Code Online (Sandbox Code Playgroud)

它可以包含在一个很好的功能中:

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);
Run Code Online (Sandbox Code Playgroud)

如果您不需要这样做,那就是Array#filter:

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


par*_*ent 66

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

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

~removeIndex && array.splice(removeIndex, 1);
Run Code Online (Sandbox Code Playgroud)

  • 或者如果你对最后一行的波形符号感到困惑,你可能会发现它更清楚:(removeIndex> = 0)&& array.splice(removeIndex,1); (7认同)
  • 这是一个非常优雅的答案。 (2认同)
  • @parliament - 在您的示例中是否有关于波浪号的任何文档?我以前从未见过这个。 (2认同)

Rah*_* R. 30

使用lodash /下划线:

如果要修改现有数组本身,则必须使用splice.这是使用findWhere of underscore/lodash的更好/可读的方式:

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);
Run Code Online (Sandbox Code Playgroud)

使用ES5或更高版本

(没有lodash /下划线)

从ES5开始,我们findIndex在阵列上有方法,所以很容易没有lodash /下划线

items.splice(items.findIndex(function(i){
    return i.id === "abc";
}), 1);
Run Code Online (Sandbox Code Playgroud)

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

关于findIndex

  • 喜欢这个 ES5 建议,因为它甚至可以用更短的方式编写 ```items.splice(items.findIndex(i =&gt; i.id === "abc"), 1)``` (8认同)
  • 请小心。这不会删除数组中具有相同“id”的所有对象。 (2认同)

Nar*_*uri 28

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

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


fat*_*ode 25

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);
Run Code Online (Sandbox Code Playgroud)

  • 与其他人相比,答案非常简单,工作得很好. (2认同)

小智 10

如果您只想将其从现有阵列中删除而不是创建新阵列,请尝试:

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

  • 请注意,这个答案需要**下划线**库 (5认同)
  • 我不推荐这个,因为如果找不到元素_.indexOf将返回-1 => items.splice(-1,1) (2认同)

Fel*_*abe 7

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

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

    if (listToDelete.indexOf(obj.id) !== -1) {
        arrayOfObjects.splice(i, 1);
    }
}
Run Code Online (Sandbox Code Playgroud)

或使用filter

var newArray = arrayOfObjects.filter(function(obj) {
    return listToDelete.indexOf(obj.id) === -1;
});
Run Code Online (Sandbox Code Playgroud)


Mir*_*ski 7

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

  let result = arrayOfObjects.filter( el => (-1 == listToDelete.indexOf(el.id)) );
  console.log(result);
Run Code Online (Sandbox Code Playgroud)

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


Syl*_*oux 5

请使用原生JavaScript.

作为替代方案,使用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' } ]
Run Code Online (Sandbox Code Playgroud)

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

reduceRight不会直接改变调用它的对象,但是对象可能会被callbackfn的调用所突变.

所以这是一个有效的用法reduceRight.