JS:从嵌套数组中删除对象并返回父数组
Posted
技术标签:
【中文标题】JS:从嵌套数组中删除对象并返回父数组【英文标题】:JS: Remove object from nested array and return parent array 【发布时间】:2017-06-19 16:39:57 【问题描述】:如何删除嵌套在另一个数组中的数组 subBrands 中的对象,其中对象的 id 属性为 = 31。我正在尝试在不删除该子品牌的情况下取回整个父数组。
数组是:
[
"id": 10,
"name": "Parent Brand 1",
"parent": null,
"author": 1,
"deleted_at": null,
"created_at": "2017-02-02 09:55:51",
"updated_at": "2017-02-02 09:55:51",
"subBrands": [
"id": 31,
"name": "Sub Brand 6",
"parent": 10,
"author": 1,
"deleted_at": null,
"created_at": "2017-02-02 11:24:49",
"updated_at": "2017-02-02 11:42:02"
,
"id": 32,
"name": "Sub Brand 7",
"parent": 10,
"author": 1,
"deleted_at": null,
"created_at": "2017-02-02 11:24:57",
"updated_at": "2017-02-02 11:42:18"
,
"id": 33,
"name": "Sub Brand 8",
"parent": 10,
"author": 1,
"deleted_at": null,
"created_at": "2017-02-02 11:25:04",
"updated_at": "2017-02-02 11:42:34"
,
"id": 34,
"name": "Sub Brand 9",
"parent": 10,
"author": 1,
"deleted_at": null,
"created_at": "2017-02-02 11:25:39",
"updated_at": "2017-02-02 11:42:43"
,
"id": 35,
"name": "Sub Brand 10",
"parent": 10,
"author": 1,
"deleted_at": null,
"created_at": "2017-02-02 11:25:46",
"updated_at": "2017-02-02 11:42:52"
,
"id": 36,
"name": "Sub Brand 4",
"parent": 10,
"author": 1,
"deleted_at": null,
"created_at": "2017-02-02 11:43:53",
"updated_at": "2017-02-02 11:43:53"
]
,
"id": 12,
"name": "Parent Brand 2",
"parent": null,
"author": 1,
"deleted_at": null,
"created_at": "2017-02-02 09:56:16",
"updated_at": "2017-02-02 09:56:16",
"subBrands": []
,
"id": 16,
"name": "Brand no children",
"parent": null,
"author": 1,
"deleted_at": null,
"created_at": "2017-02-02 10:37:40",
"updated_at": "2017-02-02 10:37:40",
"subBrands": []
,
"id": 37,
"name": "Whoops brand",
"parent": null,
"author": 1,
"deleted_at": null,
"created_at": "2017-02-02 11:44:10",
"updated_at": "2017-02-02 11:44:10",
"subBrands": []
]
我想要得到的是:
[
"id": 10,
"name": "Parent Brand 1",
"parent": null,
"author": 1,
"deleted_at": null,
"created_at": "2017-02-02 09:55:51",
"updated_at": "2017-02-02 09:55:51",
"subBrands": [
"id": 32,
"name": "Sub Brand 7",
"parent": 10,
"author": 1,
"deleted_at": null,
"created_at": "2017-02-02 11:24:57",
"updated_at": "2017-02-02 11:42:18"
,
"id": 33,
"name": "Sub Brand 8",
"parent": 10,
"author": 1,
"deleted_at": null,
"created_at": "2017-02-02 11:25:04",
"updated_at": "2017-02-02 11:42:34"
,
"id": 34,
"name": "Sub Brand 9",
"parent": 10,
"author": 1,
"deleted_at": null,
"created_at": "2017-02-02 11:25:39",
"updated_at": "2017-02-02 11:42:43"
,
"id": 35,
"name": "Sub Brand 10",
"parent": 10,
"author": 1,
"deleted_at": null,
"created_at": "2017-02-02 11:25:46",
"updated_at": "2017-02-02 11:42:52"
,
"id": 36,
"name": "Sub Brand 4",
"parent": 10,
"author": 1,
"deleted_at": null,
"created_at": "2017-02-02 11:43:53",
"updated_at": "2017-02-02 11:43:53"
]
,
"id": 12,
"name": "Parent Brand 2",
"parent": null,
"author": 1,
"deleted_at": null,
"created_at": "2017-02-02 09:56:16",
"updated_at": "2017-02-02 09:56:16",
"subBrands": []
,
"id": 16,
"name": "Brand no children",
"parent": null,
"author": 1,
"deleted_at": null,
"created_at": "2017-02-02 10:37:40",
"updated_at": "2017-02-02 10:37:40",
"subBrands": []
,
"id": 37,
"name": "Whoops brand",
"parent": null,
"author": 1,
"deleted_at": null,
"created_at": "2017-02-02 11:44:10",
"updated_at": "2017-02-02 11:44:10",
"subBrands": []
]
我愿意使用下划线。我最接近的是:
var brands = _.filter(brands, function(n)
return _.some(n.subBrands, function(subBrand)
return subBrand.id != brand.id;
);
);
但这会删除不包含 id 为 31 的子品牌的数组。所以它不是很接近我需要的。
干杯!
【问题讨论】:
它应该适用于任何深度吗?还是只为第二级? @NinaScholz 目前我只需要第二级。希望不再需要它。 “我正在尝试在不删除子品牌的情况下取回整个父数组。”您的意思是删除了对象吗? @guest271314 没有 ID 为 31 的子品牌,整个事情都不会回来。第二个数组是我试图找回的示例。 @BarryWalsh 是的,您是否要从subBrands
数组中删除带有 id
31
的对象?
【参考方案1】:
var arr = ["id":10,"name":"Parent Brand 1","parent":null,"author":1,"deleted_at":null,"created_at":"2017-02-02 09:55:51","updated_at":"2017-02-02 09:55:51","subBrands":["id":31,"name":"Sub Brand 6","parent":10,"author":1,"deleted_at":null,"created_at":"2017-02-02 11:24:49","updated_at":"2017-02-02 11:42:02","id":32,"name":"Sub Brand 7","parent":10,"author":1,"deleted_at":null,"created_at":"2017-02-02 11:24:57","updated_at":"2017-02-02 11:42:18","id":33,"name":"Sub Brand 8","parent":10,"author":1,"deleted_at":null,"created_at":"2017-02-02 11:25:04","updated_at":"2017-02-02 11:42:34","id":34,"name":"Sub Brand 9","parent":10,"author":1,"deleted_at":null,"created_at":"2017-02-02 11:25:39","updated_at":"2017-02-02 11:42:43","id":35,"name":"Sub Brand 10","parent":10,"author":1,"deleted_at":null,"created_at":"2017-02-02 11:25:46","updated_at":"2017-02-02 11:42:52","id":36,"name":"Sub Brand 4","parent":10,"author":1,"deleted_at":null,"created_at":"2017-02-02 11:43:53","updated_at":"2017-02-02 11:43:53"],"id":12,"name":"Parent Brand 2","parent":null,"author":1,"deleted_at":null,"created_at":"2017-02-02 09:56:16","updated_at":"2017-02-02 09:56:16","subBrands":[],"id":16,"name":"Brand no children","parent":null,"author":1,"deleted_at":null,"created_at":"2017-02-02 10:37:40","updated_at":"2017-02-02 10:37:40","subBrands":[],"id":37,"name":"Whoops brand","parent":null,"author":1,"deleted_at":null,"created_at":"2017-02-02 11:44:10","updated_at":"2017-02-02 11:44:10","subBrands":[]];
var id = prompt("Id of subbrands to remove: ");
arr.forEach(function(o)
o.subBrands = o.subBrands.filter(s => s.id != id);
);
console.log(arr);
【讨论】:
您通过过滤数组来创建所有新的引用。为此目的,这看起来有点过头了,即使没有具有所需 id 的对象,您也会产生一个新数组。 为什么每次迭代都要在.forEach()
创建一个新数组,而要求是从现有数组中删除一个对象?
@NinaScholz @guest271314 如果您认为唯一的其他方法是在每个找到的元素上调用forEach
和splice
,这将是最好的。
@ibrahimmahrir “如果您认为唯一的其他方法是在每个找到的元素上调用 forEach
和 splice
,这将是最好的。”不是唯一的其他可能的方法。那是您选择使用的模式。 “最好”是什么意思?无需创建新数组即可达到从现有数组中删除对象的预期结果。
@BarryWalsh,我不知道,如果我是合适的人,我的建议如下,但无论如何你需要一个原始数组和另一个没有特定 ID 的数组吗?还是只有一个?【参考方案2】:
您可以迭代父部分和子部分,如果找到则拼接对象。
var data = [ id: 10, name: "Parent Brand 1", parent: null, author: 1, deleted_at: null, created_at: "2017-02-02 09:55:51", updated_at: "2017-02-02 09:55:51", subBrands: [ id: 31, name: "Sub Brand 6", parent: 10, author: 1, deleted_at: null, created_at: "2017-02-02 11:24:49", updated_at: "2017-02-02 11:42:02" , id: 32, name: "Sub Brand 7", parent: 10, author: 1, deleted_at: null, created_at: "2017-02-02 11:24:57", updated_at: "2017-02-02 11:42:18" , id: 33, name: "Sub Brand 8", parent: 10, author: 1, deleted_at: null, created_at: "2017-02-02 11:25:04", updated_at: "2017-02-02 11:42:34" , id: 34, name: "Sub Brand 9", parent: 10, author: 1, deleted_at: null, created_at: "2017-02-02 11:25:39", updated_at: "2017-02-02 11:42:43" , id: 35, name: "Sub Brand 10", parent: 10, author: 1, deleted_at: null, created_at: "2017-02-02 11:25:46", updated_at: "2017-02-02 11:42:52" , id: 36, name: "Sub Brand 4", parent: 10, author: 1, deleted_at: null, created_at: "2017-02-02 11:43:53", updated_at: "2017-02-02 11:43:53" ] , id: 12, name: "Parent Brand 2", parent: null, author: 1, deleted_at: null, created_at: "2017-02-02 09:56:16", updated_at: "2017-02-02 09:56:16", subBrands: [] , id: 16, name: "Brand no children", parent: null, author: 1, deleted_at: null, created_at: "2017-02-02 10:37:40", updated_at: "2017-02-02 10:37:40", subBrands: [] , id: 37, name: "Whoops brand", parent: null, author: 1, deleted_at: null, created_at: "2017-02-02 11:44:10", updated_at: "2017-02-02 11:44:10", subBrands: [] ];
data.some(function (a)
return a.subBrands.some(function (b, i, bb)
if (b.id === 31)
bb.splice(i, 1);
return true;
);
);
console.log(data);
.as-console-wrapper max-height: 100% !important; top: 0;
【讨论】:
这将仅删除包含它们的第一个找到的对象的匹配子品牌。考虑arr = [sb: [id:31], sb: [id:31], sb: [id:31]]
将仅删除some
找到的第一个对象。
@ibrahimmahrir,我假设所有id
都是独一无二的。无需过滤所有子数组。这会生成新的引用,这是不必要的。保护环境。
我不是在谈论 subBrands 数组本身(那些 ID 应该是唯一的)。我说的是包含 subBrand 数组的不同对象。
另外,这不是some
的典型用法。它应该仅用于检查项目是否符合某些条件(作为其他内容的前瞻)。
@ibrahimmahrir “另外,这不是 some 的典型用法。它应该仅用于检查项目是否符合某些条件(作为其他内容的前瞻)。”我> ? “应该使用”是什么意思?对不同任务使用Array.prototype
方法没有任何限制。【参考方案3】:
我嵌套了两个forEach
循环,并在找到并删除该项目时返回:
let items = [id: 1, subItems: [id: 1, id: 2]];
const subItemToBeRemovedId = 1;
items.forEach((item) => item.subItems.forEach((subItem, index) =>
if (subItem.id === subItemToBeRemovedId)
return item.subItems.splice(index, 1);
));
console.log(items);
【讨论】:
【参考方案4】:foreach 似乎有效:
var brands=[id:10,name:"Parent Brand 1",parent:null,author:1,deleted_at:null,created_at:"2017-02-02 09:55:51",updated_at:"2017-02-02 09:55:51",subBrands:[id:31,name:"Sub Brand 6",parent:10,author:1,deleted_at:null,created_at:"2017-02-02 11:24:49",updated_at:"2017-02-02 11:42:02",id:32,name:"Sub Brand 7",parent:10,author:1,deleted_at:null,created_at:"2017-02-02 11:24:57",updated_at:"2017-02-02 11:42:18",id:33,name:"Sub Brand 8",parent:10,author:1,deleted_at:null,created_at:"2017-02-02 11:25:04",updated_at:"2017-02-02 11:42:34",id:34,name:"Sub Brand 9",parent:10,author:1,deleted_at:null,created_at:"2017-02-02 11:25:39",updated_at:"2017-02-02 11:42:43",id:35,name:"Sub Brand 10",parent:10,author:1,deleted_at:null,created_at:"2017-02-02 11:25:46",updated_at:"2017-02-02 11:42:52",id:36,name:"Sub Brand 4",parent:10,author:1,deleted_at:null,created_at:"2017-02-02 11:43:53",updated_at:"2017-02-02 11:43:53"],id:12,name:"Parent Brand 2",parent:null,author:1,deleted_at:null,created_at:"2017-02-02 09:56:16",updated_at:"2017-02-02 09:56:16",subBrands:[],id:16,name:"Brand no children",parent:null,author:1,deleted_at:null,created_at:"2017-02-02 10:37:40",updated_at:"2017-02-02 10:37:40",subBrands:[],id:37,name:"Whoops brand",parent:null,author:1,deleted_at:null,created_at:"2017-02-02 11:44:10",updated_at:"2017-02-02 11:44:10",subBrands:[]];
brands.forEach(function(brand)
brand.subBrands = brand.subBrands.filter(function(subBrand)
return subBrand.id != 31;
)
);
console.log(brands);
【讨论】:
【参考方案5】:如果您只需要查看数组中每个项目的“subBrands”属性,并且您使用的是下划线,则此方法有效:
var myBrand = _.each(brands, function(brand)
brand.subBrands = _.filter(brand.subBrands, function(subBrand)
return subBrand.id != 31;
);
);
【讨论】:
【参考方案6】:jQuery 方式
function removeById(data, id)
$(data).each(function(i, e)
if(e.subBrands.length > 0)
$(e.subBrands).each(function(_i, _e)
if(_e.id == id)
e.subBrands.splice(_i,1);
return false;
);
);
return data;
console.log(removeById(data,32))
此函数将返回您的整个数据数组,不包含特定的 id 对象
【讨论】:
【参考方案7】:您可以使用for..of
循环来迭代每个subBrands
数组,Array.prototype.splice()
以从数组中删除具有id
31
的对象。
for (let subBrands of data)
let n = 0;
for (let id of subBrands)
if (id === 31)
subBrands.splice(n, 1);
break;
++n;
【讨论】:
以上是关于JS:从嵌套数组中删除对象并返回父数组的主要内容,如果未能解决你的问题,请参考以下文章