使用JavaScript从数组中删除对象

787

如何从数组中删除一个对象? 我想要从someArray中删除包含名字Kristian的对象。例如:

someArray = [{name:"Kristian", lines:"2,5,10"},
             {name:"John", lines:"1,19,26,96"}];

我想要实现:

someArray = [{name:"John", lines:"1,19,26,96"}];
32个回答

1021

您可以使用多种方法从数组中删除元素:

//1
someArray.shift(); // first element removed
//2
someArray = someArray.slice(1); // first element removed
//3
someArray.splice(0, 1); // first element removed
//4
someArray.pop(); // last element removed
//5
someArray = someArray.slice(0, someArray.length - 1); // last element removed
//6
someArray.length = someArray.length - 1; // last element removed

如果您想要删除位置为x的元素,请使用:

someArray.splice(x, 1);

或者

someArray = someArray.slice(0, x).concat(someArray.slice(-x));
回复 @chill182 的评论:您可以使用 Array.filter 或结合 Array.findIndexArray.splice 来从数组中移除一个或多个元素(请参阅 MDN)。

参见此 Stackblitz 项目 或下面的代码段:

// non destructive filter > noJohn = John removed, but someArray will not change
let someArray = getArray();
let noJohn = someArray.filter( el => el.name !== "John" ); 
log(`let noJohn = someArray.filter( el => el.name !== "John")`,
  `non destructive filter [noJohn] =`, format(noJohn));
log(`**someArray.length ${someArray.length}`);

// destructive filter/reassign John removed > someArray2 =
let someArray2 = getArray();
someArray2 = someArray2.filter( el => el.name !== "John" );
log("", 
  `someArray2 = someArray2.filter( el => el.name !== "John" )`,
  `destructive filter/reassign John removed [someArray2] =`, 
  format(someArray2));
log(`**someArray2.length after filter ${someArray2.length}`);

// destructive splice /w findIndex Brian remains > someArray3 =
let someArray3 = getArray();
someArray3.splice(someArray3.findIndex(v => v.name === "Kristian"), 1);
someArray3.splice(someArray3.findIndex(v => v.name === "John"), 1);
log("",
  `someArray3.splice(someArray3.findIndex(v => v.name === "Kristian"), 1),`,
  `destructive splice /w findIndex Brian remains [someArray3] =`, 
  format(someArray3));
log(`**someArray3.length after splice ${someArray3.length}`);

// if you're not sure about the contents of your array, 
// you should check the results of findIndex first
let someArray4 = getArray();
const indx = someArray4.findIndex(v => v.name === "Michael");
someArray4.splice(indx, indx >= 0 ? 1 : 0);
log("", `someArray4.splice(indx, indx >= 0 ? 1 : 0)`,
  `check findIndex result first [someArray4] = (nothing is removed)`,
  format(someArray4));
log(`**someArray4.length (should still be 3) ${someArray4.length}`);

// -- helpers -- 
function format(obj) {
  return JSON.stringify(obj, null, " ");
}

function log(...txt) {
  document.querySelector("pre").textContent += `${txt.join("\n")}\n`
}

function getArray() {
  return [ {name: "Kristian", lines: "2,5,10"},
           {name: "John", lines: "1,19,26,96"},
           {name: "Brian", lines: "3,9,62,36"} ];
}
<pre>
**Results**

</pre>


2
@Klemzy,你是不是想说的不是按索引而是按值呢? - Royi Namir
487
原始问题询问如何从数组中删除名称为“Kristian”的对象。你的答案假设它是数组中的第一个项目,但如果Kristin不在第一个项目中怎么办?那么你的答案就不适用了。 - Rochelle C
12
@chill182的话并不是一个具体的答案,而是更加普遍的回答。通过这个回答,你应该可以推断出移除元素的方法。如果你想要移除位置为x的元素... 这可能是移除除第一个元素以外其他元素的提示,对吧? - KooiInc
6
splice函数对我很有帮助,但你不应该重新赋值someArray。这样会导致someArray包含已删除的项目,而不是包含已删除项目的结果数组。 - Kenn Cal
3
这怎么成为被接受的答案了呢...? - user5734311
显示剩余3条评论

313

一个干净的解决方案是使用Array.filter

var filtered = someArray.filter(function(el) { return el.Name != "Kristian"; }); 

这个方法存在的问题是,在IE < 9中它无法工作。但是,你可以引入一个JavaScript库的代码(例如underscore.js),来为任何浏览器实现此功能。


12
然而,这将删除所有发现的出现次数,而不仅仅是第一个。 - Flavien Volken
12
它会返回一个新的数组,而不是修改原始数组。根据使用情况,这可能是您想要的,也可能不是。 - Jochie Nabuurs
1
@JochieNabuurs 这确实是一个新数组。但是,对象仍然保持不变。您仍然可以修改每个对象的值,并且它将反映在原始数组的对象上。 - DriLLFreAK100
9
关于返回一个新数组的问题,只需将解决方案更改为 someArray = someArray.filter(function(el) { return el.Name != "Kristian"; }); 是否已解决此问题? - hBrent
这个回答比被采纳的回答更简单直接地回答了问题。 - tog22
显示剩余2条评论

149

我建议在处理这种常见任务时使用 lodash.js 或 sugar.js


// lodash.js
someArray = _.reject(someArray, function(el) { return el.Name === "Kristian"; });

// sugar.js
someArray.remove(function(el) { return el.Name === "Kristian"; });

在大多数项目中,使用像这样的库提供的一组辅助方法非常有用。


13
我认为下划线的示例有点不对。应该写成 someArray = _.reject(someArray, function(el) { return el.Name === "Kristian"; }); - Andy Ford
12
如果你不想使用underscore.js或sugar.js,你可以使用以下代码:someArray = someArray.filter(function(e) { return e.Name !== "Kristian"; }); 这行代码的作用是从数组中筛选出 Name 属性不等于 "Kristian" 的元素,并重新赋值给 someArray 变量。 - BenR
2
另外一个我想要的是,每个数组对象都有单独的按钮。如果我想要删除数组中特定的对象,需要点击相应的按钮。我已经使用了AngularJS的ng-repeat来生成这些项。你能帮我吗? - Thilak Raj
16
在这里我会提出异议,建议你将整个库包含在代码中只是为了从对象中删除项目(而js已经提供了这种功能,正如被接受的答案所示)是不好的做法。除非您已经需要它提供更强大的功能,否则这会给您的代码增加不必要的负担和复杂性。 - Josh Doebbert
9
为了简化操作,我永远不会建议包含库。 - Munna Bhakta
显示剩余4条评论

123

ES2015

->

ES2015

let someArray = [
               {name:"Kristian", lines:"2,5,10"},
               {name:"John", lines:"1,19,26,96"},
               {name:"Kristian", lines:"2,58,160"},
               {name:"Felix", lines:"1,19,26,96"}
            ];

someArray = someArray.filter(person => person.name != 'John');

它将删除John


16
从Java转过来,我非常困惑,为什么做这样一个基本的事情需要对列表进行过滤... 真是醉了。这是我迄今为止读到的最准确的回答OP问题的答案。 - codepleb
是的,这是一个好方法。尽管在ES2015(ES6)之前也可以工作。自2011年以来,过滤函数已经可用于5.1版本https://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.20 - user3777549
好的,干净 :) - RobbB
我在我的案例中使用了这个一行代码解决方案,并且取得了成功,它非常适应:条件可以很容易地定制。 - jhice

94

这个怎么样?

$.each(someArray, function(i){
    if(someArray[i].name === 'Kristian') {
        someArray.splice(i,1);
        return false;
    }
});

8
如果你移除了一个元素,$.each() 循环时会缓存数组的长度,这样会导致错误吗?也就是说,$.each() 会超出现在更短的数组长度进行循环。因此,someArray[i] 将是 undefined,而 undefined.name 将会导致崩溃。 - nnnnnn
5
在 splice 后面添加 'return false'。 - Allan Taylor
30
这不是 JavaScript。-1 - onionpsy
32
请注意,这个答案需要 jQuery。 - Clarkey

76
您展示的"array"是无效的 JavaScript 语法。花括号 {} 是用于具有属性名/值对的对象,但方括号 [] 是用于数组 - 就像这样:
someArray = [{name:"Kristian", lines:"2,5,10"}, {name:"John", lines:"1,19,26,96"}];

在这种情况下,您可以使用.splice()方法来删除项目。要删除第一个项目(索引0),请说:
someArray.splice(0,1);

// someArray = [{name:"John", lines:"1,19,26,96"}];

如果您不知道索引,但希望通过搜索数组来查找名称为“Kristian”的项目进行删除,则可以执行以下操作:

for (var i =0; i < someArray.length; i++)
   if (someArray[i].name === "Kristian") {
      someArray.splice(i,1);
      break;
   }

编辑:我刚注意到你的问题标记了"jQuery",所以你可以尝试使用$.grep()方法

someArray = $.grep(someArray,
                   function(o,i) { return o.name === "Kristian"; },
                   true);

为什么要添加重载?你肯定可以只写 != "Kristian"。重载有什么作用? - markthewizard1234
@markthewizard1234 - 你是指 $.grep() 中的 "invert" 布尔参数吗?在这个例子中它并没有增加太多,因为我本可以使用 !=。但在其他情况下,你可能已经定义了一个函数,恰好执行与你想要 grep 的相反测试,那么你可以使用该重载来反转结果,而不必定义额外的函数。 - nnnnnn
啊,如果你有一个包含 grep 的包装函数,你可以将布尔值设置为参数。明白了,谢谢! - markthewizard1234
@markthewizard1234 - 你可以这样做,但那不是我想要的:想象一下你有一个 function isEven(num) { return num%2===0 }。你可以使用 $.grep(someArray, isEven) 来从数组中获取仅包含偶数的值,或者使用 $.grep(someArray, isEven, true) 来获取非偶数值。 - nnnnnn

60
你可以使用 array.filter()。
例如:
        someArray = [{name:"Kristian", lines:"2,5,10"},
                     {name:"John", lines:"1,19,26,96"}];

        someArray = someArray.filter(function(returnableObjects){
               return returnableObjects.name !== 'Kristian';
        });

        //someArray will now be = [{name:"John", lines:"1,19,26,96"}];
箭头函数:
someArray = someArray.filter(x => x.name !== 'Kristian')

另外一个我想要的是,每个数组对象都有单独的按钮。如果我想要删除数组中特定的对象,需要点击相应的按钮。我已经使用了AngularJS的ng-repeat来生成这些项。你能帮我吗? - Thilak Raj
daCoda如果你有两个条件怎么办? - Malcolm Salvador
@MalcolmSalvador 举个例子,如果你有其他条件,你可以像下面这样编写,并根据你的需要使用不同的&&或||运算符继续。someArray = someArray.filter(function(returnableObjects){ return returnableObjects.name !== 'Kristian' && cond2Query.age >= 22; }); - Biswajit Panday

22
const someArray = [{name:"Kristian", lines:"2,5,10"}, {name:"John", lines:"1,19,26,96"}];

我们获取名称属性值为“Kristian”的对象的索引。

const index = someArray.findIndex(key => key.name === "Kristian");
console.log(index); // 0

通过使用splice函数,我们正在删除具有名称属性值为“Kristian”的对象

someArray.splice(index,1);
console.log(someArray); // [{name:"John", lines:"1,19,26,96"}]

3
其中一个完美的答案。上面的其余部分都是浪费时间。 - sg28
@sg28 非常感谢,我看到没有人解释它。 - Sandeep Mukherjee

21

这是一个对我有效的函数:

function removeFromArray(array, value) {
    var idx = array.indexOf(value);
    if (idx !== -1) {
        array.splice(idx, 1);
    }
    return array;
}

20

我已经制作了一个动态函数,该函数接受对象数组、键和值,并在删除所需对象后返回相同的数组:

function removeFunction (myObjects,prop,valu)
        {
             return myObjects.filter(function (val) {
              return val[prop] !== valu;
          });

        }

完整示例:演示

var obj = {
            "results": [
              {
                  "id": "460",
                  "name": "Widget 1",
                  "loc": "Shed"
              }, {
                  "id": "461",
                  "name": "Widget 2",
                  "loc": "Kitchen"
              }, {
                  "id": "462",
                  "name": "Widget 3",
                  "loc": "bath"
              }
            ]
            };


        function removeFunction (myObjects,prop,valu)
        {
             return myObjects.filter(function (val) {
              return val[prop] !== valu;
          });

        }


console.log(removeFunction(obj.results,"id","460"));

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