简体   繁体   English

将对象重组为嵌套数组的 2 个数组

[英]Restructure 2 Arrays with Objects as a Nested Array

The goal is to create a new nested array based on 2 flat arrays with objects.目标是基于 2 个带有对象的平面数组创建一个新的嵌套数组。 If an id from list B matches a refId in list A, the object is added as a child to the object in list A. This creates a new array 2 levels deep as shown in the example.如果列表 B 中的 id 与列表 A 中的 refId 匹配,则该对象将作为子项添加到列表 A 中的对象。这将创建一个 2 层深的新数组,如示例所示。

However in List B, there are objects that have id's that match refId's of their sibling objects.但是在列表 B 中,有些对象的 id 与其兄弟对象的 refId 匹配。 If such is the case the code should find matches and then add them as children of children of parent object.如果是这种情况,代码应该找到匹配项,然后将它们添加为父对象的子对象的子对象。 Thus, 3 levels deep.因此,深 3 级。 The code should continue to nest until there are no possible matches.代码应该继续嵌套,直到没有可能的匹配。

How can the below code be modified to nest any # of levels deep based matching id's and refId's?如何修改以下代码以嵌套任何基于深度匹配的 id 和 refId 的级别?

 // TOP LEVEL const listA = [ { "id": 23, "refId": 23, "name": 'list A #1', "isNested": false, "depth": 1, "children": [] }, { "id": 25, "refId": 25, "name": 'list A #1', "isNested": false, "depth": 1, "children": [] } ] // NO HEIRARCHY const listB = [ { "id": 23, "refId": 1234, "name": "test 1", "isNested": true, "depth": 2, "children": [] }, { "id": 25, "refId": 1212, "name": "test 1", "isNested": true, "depth": 2, "children": [] }, { "id": 1234, "refId": 4324, "depth": 3, "name": "test 2", "isNested": true, "children": [] }, { "id": 1234, "refId": 5678, "depth": 3, "name": "test 3", "isNested": true, "children": [] } ] const nestedArr = listA.map( ({ id, name, refId, children }) => { return { id, name, refId, children: listB.filter((b) => { return b.id == refId ? b : '' }), } } ) console.log(nestedArr)

If your refs are in order, you can do the following:如果您的 refs 是有序的,您可以执行以下操作:

  • Concat both arrays连接两个数组
  • For every element,对于每一个元素,
    • Store the ref in a Map so you can easily access it later将 ref 存储在Map中,以便您以后可以轻松访问它
    • If id === refId , push it as a top level ref如果id === refId ,将其作为顶级 ref 推送
    • If not, look up its parent and push it to the children array如果没有,则查找其父级并将其推送到children级数组
const refs = new Map();
const nestedArr = [];

for (const ref of listA.concat(listB)) {
  refs.set(ref.refId, ref);
  
  if (ref.id !== ref.refId) {
    refs.get(ref.id).children.push(ref);
  } else {
    nestedArr.push(ref);
  }
}

console.log(nestedArr)

Here's a runnable snippet:这是一个可运行的片段:

 // TOP LEVEL const listA = [ { "id": 23, "refId": 23, "name": 'list A #1', "isNested": false, "depth": 1, "children": [] }, { "id": 25, "refId": 25, "name": 'list A #1', "isNested": false, "depth": 1, "children": [] } ] // NO HEIRARCHY const listB = [ { "id": 23, "refId": 1234, "name": "test 1", "isNested": true, "depth": 2, "children": [] }, { "id": 25, "refId": 1212, "name": "test 1", "isNested": true, "depth": 2, "children": [] }, { "id": 1234, "refId": 4324, "depth": 3, "name": "test 2", "isNested": true, "children": [] }, { "id": 1234, "refId": 5678, "depth": 3, "name": "test 3", "isNested": true, "children": [] } ]; const refs = new Map(); const nestedArr = []; for (const ref of listA.concat(listB)) { refs.set(ref.refId, ref); if (ref.id !== ref.refId) { refs.get(ref.id).children.push(ref); } else { nestedArr.push(ref); } } console.log(nestedArr)

Note: this mutates the original elements注意:这会改变原始元素

You could create a Map keyed by all refId and relate to them the corresponding node objects, using the Map constructor.您可以使用Map构造函数创建一个由所有refId键入的 Map 并与相应的节点对象相关联。 Then iterate the second list to make the attachments.然后迭代第二个列表以制作附件。

This mutates the existing children arrays, so listA will have the result:这会改变现有的children数组,因此listA将得到结果:

 const listA = [{"id": 23,"refId": 23,"name": 'list A #1',"isNested": false,"depth": 1,"children": []},{"id": 25,"refId": 25,"name": 'list A #1',"isNested": false,"depth": 1,"children": []}]; const listB = [{"id": 23,"refId": 1234,"name": "test 1","isNested": true,"depth": 2,"children": []},{"id": 25,"refId": 1212,"name": "test 1","isNested": true,"depth": 2,"children": []},{"id": 1234,"refId": 4324,"depth": 3,"name": "test 2","isNested": true,"children": []},{"id": 1234,"refId": 5678,"depth": 3,"name": "test 3","isNested": true,"children": []}]; const map = new Map(listA.concat(listB).map(node => [node.refId, node])); for (const {id, refId} of listB) map.get(id).children.push(map.get(refId)); console.log(listA);

If you don't want to mutate the original input, then make sure to create new children arrays:如果您不想改变原始输入,请确保创建新的children数组:

 const listA = [{"id": 23,"refId": 23,"name": 'list A #1',"isNested": false,"depth": 1,"children": []},{"id": 25,"refId": 25,"name": 'list A #1',"isNested": false,"depth": 1,"children": []}]; const listB = [{"id": 23,"refId": 1234,"name": "test 1","isNested": true,"depth": 2,"children": []},{"id": 25,"refId": 1212,"name": "test 1","isNested": true,"depth": 2,"children": []},{"id": 1234,"refId": 4324,"depth": 3,"name": "test 2","isNested": true,"children": []},{"id": 1234,"refId": 5678,"depth": 3,"name": "test 3","isNested": true,"children": []}]; const map = new Map(listA.concat(listB).map(node => [node.refId, {...node, children:[]}])); for (const {id, refId} of listB) map.get(id).children.push(map.get(refId)); const nestedListA = listA.map(({id}) => map.get(id)); console.log(nestedListA);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM