[英]remove objects from array by object property
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
如何通过匹配 object 属性从阵列中删除 object?
请仅使用本机 JavaScript。
我在使用拼接时遇到问题,因为每次删除长度都会减少。 在原始索引上使用克隆和拼接仍然会给您带来长度减少的问题。
我假设你使用了这样的splice
?
for (var i = 0; i < arrayOfObjects.length; i++) {
var obj = arrayOfObjects[i];
if (listToDelete.indexOf(obj.id) !== -1) {
arrayOfObjects.splice(i, 1);
}
}
修复错误所需要做的就是在下一次减少i
,然后(向后循环也是一种选择):
for (var i = 0; i < arrayOfObjects.length; i++) {
var obj = arrayOfObjects[i];
if (listToDelete.indexOf(obj.id) !== -1) {
arrayOfObjects.splice(i, 1);
i--;
}
}
为了避免线性时间删除,您可以编写要保留在数组上的数组元素:
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;
为了避免现代运行时中的线性时间查找,您可以使用哈希集:
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;
它可以包含在一个很好的函数中:
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);
如果你不需要就地做,那就是Array#filter
:
const toDelete = new Set(['abc', 'efg']);
const newArray = arrayOfObjects.filter(obj => !toDelete.has(obj.id));
您可以通过其属性之一删除项目,而无需使用任何 3rd 方库,如下所示:
var removeIndex = array.map(item => item.id).indexOf("abc");
~removeIndex && array.splice(removeIndex, 1);
如果要修改现有数组本身,那么我们必须使用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);
(没有 lodash/下划线)
从 ES5 开始,我们在数组上有findIndex
方法,所以没有 lodash/underscore 更容易
items.splice(items.findIndex(function(i){
return i.id === "abc";
}), 1);
(几乎所有现代浏览器都支持 ES5)
findIndex 适用于现代浏览器:
var myArr = [{id:'a'},{id:'myid'},{id:'c'}];
var index = myArr.findIndex(function(o){
return o.id === 'myid';
})
if (index !== -1) myArr.splice(index, 1);
根据给定数组中的 id 删除对象;
const hero = [{'id' : 1, 'name' : 'hero1'}, {'id': 2, 'name' : 'hero2'}];
//remove hero1
const updatedHero = hero.filter(item => item.id !== 1);
如果您只想从现有数组中删除它而不是创建一个新数组,请尝试:
var items = [{Id: 1},{Id: 2},{Id: 3}];
items.splice(_.indexOf(items, _.find(items, function (item) { return item.Id === 2; })), 1);
通过递减i
来反向循环以避免问题:
for (var i = arrayOfObjects.length - 1; i >= 0; i--) {
var obj = arrayOfObjects[i];
if (listToDelete.indexOf(obj.id) !== -1) {
arrayOfObjects.splice(i, 1);
}
}
或使用filter
:
var newArray = arrayOfObjects.filter(function(obj) {
return listToDelete.indexOf(obj.id) === -1;
});
使用 Set 和 ES5 过滤器检查一下。
let result = arrayOfObjects.filter( el => (-1 == listToDelete.indexOf(el.id)) );
console.log(result);
这是 JsFiddle: https ://jsfiddle.net/jsq0a0p1/1/
请只使用原生 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' } ]
根据ECMA-262 中 'Array.prototype.reduceRight' 的定义:
reduceRight 不会直接改变调用它的对象,但该对象可能会通过调用 callbackfn 来改变。
所以这是reduceRight
的有效用法。
var arrayOfObjects = [{id:'abc',name:'oh'}, // delete me
{id:'efg',name:'em'}, // delete me
{id:'hij',name:'ge'}] // all that should remain
根据你的回答会是这样的。 当您单击某个特定对象时,发送参数中的索引以用于删除我的功能。 这个简单的代码会像魅力一样工作。
function deleteme(i){
if (i > -1) {
arrayOfObjects.splice(i, 1);
}
}
如果您喜欢简短且自我描述的参数,或者您不想使用splice
并使用简单的过滤器,或者您只是像我这样的 SQL 人员:
function removeFromArrayOfHash(p_array_of_hash, p_key, p_value_to_remove){
return p_array_of_hash.filter((l_cur_row) => {return l_cur_row[p_key] != p_value_to_remove});
}
以及示例用法:
l_test_arr =
[
{
post_id: 1,
post_content: "Hey I am the first hash with id 1"
},
{
post_id: 2,
post_content: "This is item 2"
},
{
post_id: 1,
post_content: "And I am the second hash with id 1"
},
{
post_id: 3,
post_content: "This is item 3"
},
];
l_test_arr = removeFromArrayOfHash(l_test_arr, "post_id", 2); // gives both of the post_id 1 hashes and the post_id 3
l_test_arr = removeFromArrayOfHash(l_test_arr, "post_id", 1); // gives only post_id 3 (since 1 was removed in previous line)
带过滤器和 indexOf
withLodash = _.filter(arrayOfObjects, (obj) => (listToDelete.indexOf(obj.id) === -1));
withoutLodash = arrayOfObjects.filter(obj => listToDelete.indexOf(obj.id) === -1);
带过滤器和包含
withLodash = _.filter(arrayOfObjects, (obj) => (!listToDelete.includes(obj.id)))
withoutLodash = arrayOfObjects.filter(obj => !listToDelete.includes(obj.id));
您可以使用filter
。 如果条件为真,此方法总是返回元素。 因此,如果您想按 id 删除,则必须保留所有与给定 id 不匹配的元素。 下面是一个例子:
arrayOfObjects = arrayOfObjects.filter(obj => obj.id != idToRemove)
一个非常简短的方法是:
for (i = 0; i < listToDelete.length; i++) {
arrayOfObjects = arrayOfObjects.filter((e) => e.id !== listToDelete[i])
}
不正确的方式
首先,任何建议使用filter
的答案实际上都不会删除该项目。 这是一个快速测试:
var numbers = [1, 2, 2, 3];
numbers.filter(x => x === 2);
console.log(numbers.length);
在上面, numbers
数组将保持不变(不会删除任何内容)。 filter
方法返回一个新数组,其中包含满足条件x === 2
的所有元素,但原始数组保持不变。
当然你可以这样做:
var numbers = [1, 2, 2, 3];
numbers = numbers.filter(x => x === 2);
console.log(numbers.length);
但这只是将一个新数组分配给numbers
。
从数组中删除项目的正确方法
正确的方法之一,不止1,是按照以下方式进行。 请记住,此处的示例故意包含重复项,因此可以考虑删除重复项。
var numbers = [1, 2, 2, 3];
// Find all items you wish to remove
// If array has objects, then change condition to x.someProperty === someValue
var numbersToRemove = numbers.filter(x => x === 2);
// Now remove them
numbersToRemove.forEach(x => numbers.splice(numbers.findIndex(n => n === x), 1));
// Now check (this is obviously just to test)
console.log(numbers.length);
console.log(numbers);
现在您会注意到length
返回 2,表示数组中只剩下数字 1 和 3。
在你的情况下
具体回答你的问题是这样的:
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
这是答案:
listToDelete.forEach(x => arrayOfObjects.splice(arrayOfObjects.findIndex(n => n.id === x), 1));
var apps = [{id:34,name:'My App',another:'thing'},{id:37,name:'My New App',another:'things'}]
var removeIndex = apps.map(function(item) { return item.id; }).indexOf(37)
apps.splice(removeIndex, 1);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.