使用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个回答

16

你也可以尝试像这样做:

var myArray = [{'name': 'test'}, {'name':'test2'}];
var myObject = {'name': 'test'};
myArray.splice(myArray.indexOf(myObject),1);

3
myArray.indexOf(myObject)返回-1,因为没有任何项与myObject引用相等。 因此,在这种情况下,splice()将从数组中删除第-1个元素,即{'name':'test2'} - Birchlabs

12
someArray = jQuery.grep(someArray , function (value) {
        return value.name != 'Kristian';
});

10

使用“splice”函数来操作数组。指定起始元素的位置和要删除的子序列长度。

someArray.splice(pos, 1);

10

性能

今天,2021年01月27日,我在MacOs HighSierra 10.13.6上测试了选定解决方案在Chrome v88、Safari v13.1.2和Firefox v84浏览器中的性能。

结果

对于所有浏览器:

  • 当元素不存在时,最快的解决方案是A和B
  • 对于大数组,最快的解决方案是C
  • 对于存在元素的大数组,最快的解决方案是H
  • 对于小数组,相对较慢的解决方案是F和G
  • 对于大数组,相对较慢的解决方案是D、E和F

enter image description here

详情

我进行了4个测试用例:

  • 小数组(10个元素)且元素存在 - 可以在此处运行
  • 小数组(10个元素)且元素不存在 - 可以在此处运行
  • 大数组(百万个元素)且元素存在 - 可以在此处运行
  • 大数组(百万个元素)且元素不存在 - 可以在此处运行

以下代码段展示了解决方案之间的差异 A B C D E F G H I

function A(arr, name) {
  let idx = arr.findIndex(o => o.name==name);
  if(idx>=0) arr.splice(idx, 1);
  return arr;
}


function B(arr, name) {
  let idx = arr.findIndex(o => o.name==name);
  return idx<0 ? arr : arr.slice(0,idx).concat(arr.slice(idx+1,arr.length));
}


function C(arr, name) {
  let idx = arr.findIndex(o => o.name==name);
  delete arr[idx];
  return arr;
}


function D(arr, name) {
  return arr.filter(el => el.name != name);
}


function E(arr, name) {
  let result = [];
  arr.forEach(o => o.name==name || result.push(o));
  return result;
}


function F(arr, name) {
  return _.reject(arr, el => el.name == name);
}


function G(arr, name) {
  let o = arr.find(o => o.name==name);
  return _.without(arr,o);
}


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


function I(arr, name) {
  return $.grep(arr,o => o.name!=name);
}








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

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

let test3 = [   
    {name:"John3", lines:"1,19,26,96"},
    {name:"John", lines:"1,19,26,96"},
  {name:"Joh2", lines:"1,19,26,96"},
];

console.log(`
Test1: original array from question
Test2: array with more data
Test3: array without element which we want to delete
`);

[A,B,C,D,E,F,G,H,I].forEach(f=> console.log(`
Test1 ${f.name}: ${JSON.stringify(f([...test1],"Kristian"))}
Test2 ${f.name}: ${JSON.stringify(f([...test2],"Kristian"))}
Test3 ${f.name}: ${JSON.stringify(f([...test3],"Kristian"))}
`));
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
  
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js" integrity="sha512-90vH1Z83AJY9DmlWa8WkjkV79yfS2n2Oxhsi2dZbIv0nC4E6m5AbH8Nh156kkM7JePmqD6tcZsfad1ueoaovww==" crossorigin="anonymous"> </script>
  
This shippet only presents functions used in performance tests - it not perform tests itself!

这里是 Chrome 浏览器的示例结果:

在此输入图片描述


10

这是一个使用map和splice的示例

const arrayObject = [
  { name: "name1", value: "value1" },
  { name: "name2", value: "value2" },
  { name: "name3", value: "value3" },
];

let index = arrayObject.map((item) => item.name).indexOf("name1");
if (index > -1) {
  arrayObject.splice(index, 1);
  console.log("Result", arrayObject);
}

输出

Result [
  {
    "name": "name2",
    "value": "value2"
  },
  {
    "name": "name3",
    "value": "value3"
  }
]

这个方法也适用于IE11,而使用 findIndex 的答案则不行。 - Narxx

9

投票支持 UndercoreJS,以便更轻松地处理数组。

_.without() 函数可以帮助您删除一个元素:

 _.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
    => [2, 3, 4]

最佳解决方案。适用于对象数组。 - Azee

6

使用ES6箭头函数

let someArray = [
                 {name:"Kristian", lines:"2,5,10"},
                 {name:"John", lines:"1,19,26,96"}
                ];
let arrayToRemove={name:"Kristian", lines:"2,5,10"};
someArray=someArray.filter((e)=>e.name !=arrayToRemove.name && e.lines!= arrayToRemove.lines)

4

虽然这可能不太适用于此情况,但我最近发现,如果您不需要改变数组的大小,也可以使用delete关键字从数组中删除项,例如:

var myArray = [1,2,3];

delete myArray[1];

console.log(myArray[1]); //undefined

console.log(myArray.length); //3 - doesn't actually shrink the array down

3

最简单的解决方案是创建一个按名称存储每个对象索引的映射,像这样:

//adding to array
var newPerson = {name:"Kristian", lines:"2,5,10"}
someMap[ newPerson.name ] = someArray.length;
someArray.push( newPerson );

//deleting from the array
var index = someMap[ 'Kristian' ];
someArray.splice( index, 1 );

我喜欢这个想法,但我还必须问一下,像这样添加索引时的内存使用限制是多少?我有一个数组,我想在对象的两个不同字段上建立索引,所以除了原始源数组之外,我还会有两个映射。为了查找速度,这是一个小代价吗?还是有更高效利用内存的解决方案? - Brad G.

3
这个答案:
for (var i =0; i < someArray.length; i++)
   if (someArray[i].name === "Kristian") {
      someArray.splice(i,1);
   }

如果有多个记录符合条件,则is not working for multiple records fulfilling the condition.如果您有两个这样的连续记录,则只删除第一个记录,而跳过另一个记录。您必须使用以下方法:

for (var i = someArray.length - 1; i>= 0; i--)
   ...

相反。


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