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
如何通过匹配对象属性从数组中删除对象?
请使用原生JavaScript。
我在使用拼接时遇到问题,因为每次删除都会缩短长度。在orignal索引上使用克隆和拼接仍然会给你带来缩短长度的问题。
Dan Kanze asked -07-17T23:34:28Z
12个解决方案
132 votes
我假设您使用过Array#filter这样的东西?
for (var i = 0; i < arrayOfObjects.length; i++) {
var obj = arrayOfObjects[i];
if (listToDelete.indexOf(obj.id) !== -1) {
arrayOfObjects.splice(i, 1);
}
}
你需要做的就是修复这个bug,下次再减少Array#filter,然后(向后循环也是一个选项):
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;
它可以包含在一个很好的功能中:
Array#filter
如果您不需要这样做,那就是Array#filter:
const toDelete = new Set(['abc', 'efg']);
const newArray = arrayOfObjects.filter(obj => !toDelete.has(obj.id));
Ry- answered -07-17T23:35:22Z
60 votes
您可以通过其中一个属性删除项目,而无需使用任何第三方库,如下所示:
var removeIndex = array.map(function(item) { return item.id; })
.indexOf("abc");
~removeIndex && array.splice(removeIndex, 1);
parliament answered -07-17T23:35:45Z
24 votes
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);
fatlinesofcode answered -07-17T23:36:09Z
24 votes
使用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);
使用ES5或更高版本
(没有lodash /下划线)
从ES5开始,我们在阵列上有findIndex方法,所以它很容易没有lodash /下划线
items.splice(items.findIndex(function(i){
return i.id === "abc";
}), 1);
(几乎所有现代浏览器都支持ES5)
关于findIndex及其浏览器兼容性
Rahul R. answered -07-17T23:37:14Z
9 votes
如果您只想将其从现有阵列中删除而不是创建新阵列,请尝试:
var items = [{Id: 1},{Id: 2},{Id: 3}];
items.splice(_.indexOf(items, _.find(items, function (item) { return item.Id === 2; })), 1);
user2704940 answered -07-17T23:37:38Z
5 votes
请使用原生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的有效用法。
Sylvain Leroux answered -07-17T23:38:26Z
4 votes
通过递减filter来反向循环以避免此问题:
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;
});
Felix Rabe answered -07-17T23:38:57Z
2 votes
var arrayOfObjects = [{id:'abc',name:'oh'}, // delete me
{id:'efg',name:'em'}, // delete me
{id:'hij',name:'ge'}] // all that should remain
根据你的答案将是这样的。 当你单击某个特定对象时,在param中发送删除我的函数的索引。 这个简单的代码将像魅力一样工作。
function deleteme(i){
if (i > -1) {
arrayOfObjects.splice(i, 1);
}
}
Subhojit Mondal answered -07-17T23:39:22Z
2 votes
使用Set和ES6过滤器检查这一点。
let result = arrayOfObjects.filter( el => (-1 == listToDelete.indexOf(el.id)) );
console.log(result);
这是JsFiddle:[/jsq0a0p1/1/]
Miroslav Savovski answered -07-17T23:39:53Z
1 votes
带过滤器和放大器 指数
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));
user3437231 answered -07-17T23:40:23Z
0 votes
如果您喜欢简短的自我描述性参数,或者您不想使用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)
Mehmet Kaplan answered -07-17T23:40:50Z
0 votes
在给定数组中通过它的id删除对象;
const hero = [{'id' : 1, 'name' : 'hero1'}, {'id': 2, 'name' : 'hero2'}];
//remove hero1
const updatedHero = hero.filter(item => item.id !== 1);
Naresh Chennuri answered -07-17T23:41:15Z