JS:从嵌套数组中删除对象并返回父数组

8

如何从我的数组subBrands中删除嵌套在另一个数组中的对象,其中对象的id属性等于31。我想要整个父数组返回,而不是删除那个subBrand。

数组如下:

[
  {
    "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的subBrand的数组。所以它跟我需要的还有很大差距。
祝好!

它应该适用于任何深度吗?还是只适用于第二层级别? - Nina Scholz
@NinaScholz 目前我只需要它用于第二级。希望不需要再用了。 - BarryWalsh
“我正在尝试获取完整的父数组,而不是删除那个子品牌。你的意思是要删除这个对象吗?” - guest271314
@guest271314 不,整个东西都要返回,不带子品牌,ID为31。第二个数组是我想要得到的示例。 - BarryWalsh
@BarryWalsh 是的,您是否正在尝试从subBrands数组中删除ID为31的对象? - guest271314
7个回答

19

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);


1
你可以通过过滤一个数组来创建所有新的引用。即使没有符合所需ID的对象,这看起来有点过于复杂,你也会生成一个新的数组。 - Nina Scholz
在使用 .forEach() 从现有数组中删除对象的要求下,为什么应该在每次迭代时创建一个新数组? - guest271314
如果你考虑到唯一的其他方法是在找到每个元素时调用forEachsplice,那么这将是最好的方法。@NinaScholz @guest271314 - ibrahim mahrir
1
如果您认为唯一的其他方法是对每个找到的元素调用forEachsplice,那么这将是最好的方法。但这不是唯一的其他可能方法。这只是您选择使用的模式。您所说的“最好”是什么意思?创建一个新数组并不是必要的,以达到从现有数组中删除对象的预期结果。 - guest271314
@BarryWalsh 你希望结果存储在一个新的数组中而不是覆盖原始数组吗? - ibrahim mahrir
显示剩余3条评论

4
您可以迭代父级部分和子级部分,如果找到相应对象,则对其进行剪切。

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 找到的第一个对象。 - ibrahim mahrir
1
@ibrahimmahrir,我假设所有的id都是唯一的。不需要过滤所有的子数组。这会生成新的引用,这是不必要的。保护环境。 - Nina Scholz
我不是在谈论subBrands数组本身(这些ID应该是唯一的)。我在谈论包含subBrand数组的不同对象。 - ibrahim mahrir
此外,这并不是 some 的典型用法。它应该仅用于检查一个项目是否符合某些标准(作为其他内容的前瞻)。 - ibrahim mahrir
@ibrahimmahrir "此外,这并不是some的典型用法。它应该仅用于检查一个项目是否符合某些条件(作为其他内容的前瞻)。" 你所说的“应该使用”是什么意思?对于不同的任务,可以使用Array.prototype方法而没有任何限制。 - guest271314

4

我嵌套两个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);


1

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);


0
如果您只需要查看数组中每个项目的“subBrands”属性,并且正在使用underscore,则可以使用以下方法:
var myBrand = _.each(brands, function(brand) {
  brand.subBrands = _.filter(brand.subBrands, function(subBrand) {
    return subBrand.id != 31;
  });
});

0

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对象。


0

您可以使用 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;
  }
}

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