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 如果您认为唯一的其他方法是在每个找到的元素上调用forEachsplice,这将是最好的。 @ibrahimmahrir “如果您认为唯一的其他方法是在每个找到的元素上调用 forEachsplice,这将是最好的。”不是唯一的其他可能的方法。那是您选择使用的模式。 “最好”是什么意思?无需创建新数组即可达到从现有数组中删除对象的预期结果。 @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:从嵌套数组中删除对象并返回父数组的主要内容,如果未能解决你的问题,请参考以下文章

从数组中的嵌套对象中删除对象属性

js数组对象操作

面向对象认识JS-内置对象(重点)--array

js怎么从数组中删除指定值(不是指定位置)的元素?

js内置对象中的常用方法总结

JS的数组操作