【问题标题】:Merge and nest javascript objects合并和嵌套 javascript 对象
【发布时间】:2019-07-11 19:57:14
【问题描述】:

我有两个 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:

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 } ] 

我想要实现的是将 newvehicles 的对象作为“new-cars”的子对象推入导航栏,并通过导航栏并移动任何 ParentId 不为 null 的东西被移动到那个父对象作为一个孩子

我目前正在使用 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' }       } ]

【问题讨论】:

  • 您的代码中导航元素的顺序是否一致/有保证?如果是这样,它就像navbar[2].child = newvehicles; 一样简单 - 如果不是,那么你必须先找到索引,然后分配它......
  • 不保证顺序,这就是我使用 for 循环查找索引然后设置子项的原因。我还需要为第二部分做一个 for 循环吗?查找具有 parentID 的所有项目,然后查找具有该 ID 的元素并将其作为子元素插入并从主数组中删除?
  • 那么这个解决方案(使用findIndex)结合我上面的代码,就可以了:stackoverflow.com/q/15997879/870729
  • 那些是 JS 对象。 JSON 始终是一个字符串。

标签: javascript merge


【解决方案1】:

您已经提出的循环逻辑似乎满足了您关于附加汽车逻辑的目标。但是,您的请求中隐含的是,只有一个条目带有“新车”。如果这是真的,那么请考虑:

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

对于非空的parentId,您可以:

  • 通过外部数组向后循环,
  • 在循环中,查找任何具有与当前项的 parentId 匹配的 id 的数组项,
  • 拼接出当前项(子项)
  • 将其加载到检索到的父级的“子级”属性中,

代码如下:

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' 属性允许多个子级,我们将其转换为一个数组。因此,我们首先检查父级中是否存在“子级”属性。如果不是,我们创建它并将其设置为等于一个空数组。然后,我们将拼接的子对象推入循环:

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

考虑根据您的需要将 'child' 的名称更改为 'children'。

另外,请注意,所有这些都只适用于一个级别。如果您需要将父级嵌套到子级,那么简单的循环是不够的。在这种情况下,您可能需要创建一个不同的问题。

【讨论】:

  • 有没有办法将项目推送到子项中,目前如果有两个具有相同父 ID 的项目,那么只有其中一个被添加为子项,而不是两个都作为数组
  • 感谢更新的代码,用这种方法我最终得到了一个双数组作为孩子,在这里放一些示例数据 - jsfiddle.net/0mrtvjs9/2
  • @TamoorMalik,我在拼接后添加了“[0]”,这应该可以解决问题。
【解决方案2】:

这里是基于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)
);

结果如下(抱歉,我的屏幕不够高,无法完整打印)

【讨论】:

    猜你喜欢
    • 2020-06-23
    • 2013-08-02
    • 2012-12-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-22
    • 1970-01-01
    • 2021-12-30
    • 2020-08-10
    相关资源
    最近更新 更多