合并和嵌套javascript对象

时间:2019-07-11 19:57:14

标签: javascript merge

我有两个javascript对象,我想更改其中一个的结构并将另一个合并到第一个

我已经使用循环进行了绑定,但这似乎并不是最好的方法

我的第一个对象称为“导航栏”

navbar:
   [ { Id: 7,
       ParentId: null,
       Name: 'Home',
       Slug: '/',
       Priority: 1,
       MenuDisplay: true,
       MenuSubDisplay: false,
       MobileDisplay: false,
       PageType: 'Custom Plus' },
     { Id: 15,
       ParentId: 14,
       Name: 'About Us',
       Slug: 'about-us',
       Priority: 1,
       MenuDisplay: true,
       MenuSubDisplay: false,
       MobileDisplay: false,
       PageType: 'Custom Plus' },
     { Id: 8,
       ParentId: null,
       Name: 'New Cars',
       Slug: 'new-cars',
       Priority: 2,
       MenuDisplay: true,
       MenuSubDisplay: false,
       MobileDisplay: false,
       PageType: 'Custom' },
     { Id: 14,
       ParentId: null,
       Name: 'More',
       Slug: 'more',
       Priority: 8,
       MenuDisplay: true,
       MenuSubDisplay: false,
       MobileDisplay: false,
       PageType: 'Placeholder' } ]

我的第二个叫新车:

newvehicles:
   [ { Id: 5,
       VehicleType: 'Car',
       MakeId: 5,
       MakeName: 'Make',
       MakeSlug: 'make',
       ModelId: 13,
       ModelName: 'All-New Car',
       ModelSlug: 'all-new-car',
       Prefix: null,
       Suffix: null,
       Priority: 1,
       Redirect: null,
       Image:
        'http://xxxx.jpg',
       Assets: null,
       Markup: null },
     { Id: 6,
       VehicleType: 'Car',
       MakeId: 5,
       MakeName: 'Car',
       MakeSlug: 'Car',
       ModelId: 8,
       ModelName: 'Car',
       ModelSlug: 'Car',
       Prefix: null,
       Suffix: null,
       Priority: 2,
       Redirect: null,
       Image:
        'http://xxxx.jpg',
       Assets: null,
       Markup: null } ] 

我要实现的目标是将新车的对象作为“新车”的子代推入导航栏,并通过导航栏移动任何具有不为null的ParentId的内容该父对象还是一个孩子

我目前正在使用for循环进行一些更改:

    for (var i = 0; i < navigation.navbar.length; i++) {
      var obj = navigation.navbar[i];
      if (obj.Slug == 'new-cars') {
        obj.child = newvehicles;
      }
    }

但是我正在寻找这样的输出:

navbar:
   [ { Id: 7,
       ParentId: null,
       Name: 'Home',
       Slug: '/',
       Priority: 1,
       MenuDisplay: true,
       MenuSubDisplay: false,
       MobileDisplay: false,
       PageType: 'Custom Plus' },
     { Id: 8,
       ParentId: null,
       Name: 'New Cars',
       Slug: 'new-cars',
       Priority: 2,
       MenuDisplay: true,
       MenuSubDisplay: false,
       MobileDisplay: false,
       PageType: 'Custom'.
child :  [ { Id: 5,
       VehicleType: 'Car',
       MakeId: 5,
       MakeName: 'Make',
       MakeSlug: 'make',
       ModelId: 13,
       ModelName: 'All-New Car',
       ModelSlug: 'all-new-car',
       Prefix: null,
       Suffix: null,
       Priority: 1,
       Redirect: null,
       Image:
        'http://xxxx.jpg',
       Assets: null,
       Markup: null },
     { Id: 6,
       VehicleType: 'Car',
       MakeId: 5,
       MakeName: 'Car',
       MakeSlug: 'Car',
       ModelId: 8,
       ModelName: 'Car',
       ModelSlug: 'Car',
       Prefix: null,
       Suffix: null,
       Priority: 2,
       Redirect: null,
       Image:
        'http://xxxx.jpg',
       Assets: null,
       Markup: null } ]        },
     { Id: 14,
       ParentId: null,
       Name: 'More',
       Slug: 'more',
       Priority: 8,
       MenuDisplay: true,
       MenuSubDisplay: false,
       MobileDisplay: false,
       PageType: 'Placeholder',
child:     { Id: 15,
       ParentId: 14,
       Name: 'About Us',
       Slug: 'about-us',
       Priority: 1,
       MenuDisplay: true,
       MenuSubDisplay: false,
       MobileDisplay: false,
       PageType: 'Custom Plus' }       } ]

2 个答案:

答案 0 :(得分:2)

您介绍的循环逻辑似乎已经满足您在附加汽车逻辑方面的目标。但是,您的要求中隐含的是只有一个条目带有“新车”的标签。如果是这样,请考虑:

navbar.find(item => item.Slug == 'new-cars').child = newvehicles;

关于非null parentId,您可以:

  • 向后循环遍历外部数组
  • 在循环中,找到ID与当前项的parentId匹配的所有数组项,
  • 拼接出当前项(孩子)
  • 将其加载到检索到的父级的“ child”属性中,

代码如下:

for (var i = navbar.length - 1; i >= 0; i--) {
  var obj = navbar[i];
  let parent = navbar.find(item => item.Id == obj.ParentId);
  if (parent) {
    parent.child = navbar.splice(i,1);    
  }
}

在两种情况下,均以“导航”为前缀。必要时转到“导航栏”和/或“新车”。

编辑:要处理以下OP的评论,该评论要求能够将多个孩子与父母联系起来。

为了使'child'属性允许多个孩子,我们将其转换为数组。因此,我们将首先检查父级中是否存在'child'属性。如果没有,我们将其创建并将其设置为一个空数组。然后,将拼接后的子对象推入循环:

for (var i = navbar.length - 1; i >= 0; i--) {
  var obj = navbar[i];
  let parent = navbar.find(item => item.Id == obj.ParentId);
  if (parent) {
    if (!parent.child)
        parent.child = [];
    parent.child.push(navbar.splice(i,1)[0]);    
  }
}

请考虑根据需要将“孩子”的名称更改为“孩子”。

此外,请注意,所有这些仅适用于一个级别。如果您需要父母对孩子的多层嵌套,那么简单的循环是不够的。在这种情况下,您可能想创建一个不同的问题。

答案 1 :(得分:0)

这是基于Lodash-fp

的解决方案

这是Lodash库的一种变体,它允许使用完整的函数式编程样式,并使此类任务非常容易(如果您需要一些解释,请不要犹豫)

const parentsPartition = _.partition(['ParentId', null], navbar);
const vehicleHierarchy = _.map(
    vehicle => {
        const children = _.filter(['ParentId', vehicle.Id], parentsPartition[1]);
        return _.cond([
            [_.isEmpty, _.constant(vehicle)],
            [_.stubTrue, _.set('children', _, vehicle)]
        ])(children);
    },
    _.concat(parentsPartition[0], newvehicles)
);

这是结果(对不起,我的屏幕不够高,无法完整打印)

enter image description here