简体   繁体   English

从拆分输入动态创建多维数组

[英]Dynamically create multidimensional array from split input

I have an array of ojects which all have a path and a name property.我有一个对象数组,它们都有一个路径和一个名称属性。 Like

[
{
 "id": "1",
 "path": "1",
 "name": "root"
},
{
 "id": "857",
 "path": "1/857",
 "name": "Animals"
},
{
 "id": "1194",
 "path": "1/857/1194",
 "name": "Dinasours"
},
...and so on
]

Here are some path examples以下是一些路径示例

1/1279/1282
1/1279/1281
1/1279/1280
1/857
1/857/1194
1/857/1194/1277
1/857/1194/1277/1278

I want to turn this into a multidimensional array like:我想把它变成一个多维数组,如:

const data = {
  id: "1",
  name: "Root",
  children: [
    {
      id: "1279",
      name: "Toys",
    },
    {
      id: "857",
      name: "Animals",
      children: [
        {
          id: "1194",
          name: "Dinasours",
          children: [
            {
              id: "1277",
              name: "T-Rex",
              children: [
                {
                  id: "1278",
                  name: "Superbig T-Rex",
                },
              ],
            },
          ],
        },
      ],
    },
  ],
};

As you can understand the amount of data is much larger.如您所知,数据量要大得多。

Is there a neat way to transform this data?有没有一种巧妙的方法来转换这些数据?

Assuming that the root is always the same I came up with this code, it took me some time but it was fun to think about it.假设根总是相同的,我想出了这个代码,我花了一些时间,但考虑它很有趣。

var data = {};

list.forEach(item => {
  var path = item.path.split("/");
  
  let parent = data;
  
  path.forEach((id) => {
    if (!parent.id) {
      parent.id = id;
      parent.children = [];

      if (id != item.id) {
        let next = {}
        parent.children.push(next);
        parent = next;        
      }

    } else if (parent.id != id) {
      let next = parent.children.find(child => child.id == id);

      if (!next) {
        next = { id: id, children: [] }
        parent.children.push(next);
      }
      
      parent = next;
    }
  });
  
  parent.id = item.id;
  parent.name = item.name
});

output:输出:

{
  "id": "1",
  "children": [
    {
      "id": "857",
      "children": [
        {
          "id": "1194",
          "children": [
            {
              "id": "1277",
              "children": [
                { "id": "1278", "children": [], "name": "Superbig T-Rex" }
              ],
              "name": "T-Rex"
            }
          ],
          "name": "Dinasours"
        }
      ],
      "name": "Animals"
    },
    { "id": "1279", "children": [], "name": "Toys" }
  ],
  "name": "Root"
}

I think that having more roots here may need some fixing.我认为在这里有更多的根可能需要一些修复。 Although I think the problem would be different if we were talking about multiple roots since your data variable is an object虽然我认为如果我们谈论多个根,问题会有所不同,因为您的数据变量是一个对象

Also, if you think in a recursive way it can be more understandable, but no comments on performance.此外,如果您以递归的方式思考它可以更容易理解,但没有对性能的评论。

I wonder if this would be sufficient for your needs?我想知道这是否足以满足您的需求?

I'll refer to the objects as nodes (just because I'm a graph theory person, and that's how I roll).我将这些对象称为节点(仅仅因为我是一个图论人士,这就是我滚动的方式)。

  1. Build an index mapping each id to the object itself using a Map .使用Map构建一个将每个 id 映射到对象本身的索引。 (Purely for efficiency. You could technically find each node from scratch by id each time you need it.) (纯粹是为了效率。从技术上讲,您可以在每次需要时通过 id 从头开始​​找到每个节点。)
  2. Split the path to obtain the second last path fragment which should be the id of the direct parent of the node.拆分路径以获得倒数第二个路径片段,它应该是节点的直接父节点的 id。 (Assuming there's only one and that there is guaranteed to be a node corresponding to that id?) (假设只有一个并且保证有一个节点与该 ID 对应?)
  3. Add the child to the parent's list of children.将孩子添加到父母的孩子列表中。 We'll be careful not to add it multiple times.我们会小心不要多次添加它。

This will result in nodes that have no children literally having no children property (as opposed to having a children property that is just [] ).这将导致没有子节点的节点实际上没有children属性(而不是只有[]children属性)。 I also did not remove/delete the path property from the objects.我也没有从对象中删除/删除path属性。

As a note of caution, if there are path fragments that do not have corresponding objects, this will not work.需要注意的是,如果存在没有对应对象的路径片段,这将不起作用。

 const nodes = [ { id: '1', path: '1', name: 'root' }, { id: '857', path: '1/857', name: 'Animals' }, { id: '1194', path: '1/857/1194', name: 'Dinasours' } //...and so on ]; const index = new Map(); for (let node of nodes) { index.set(node.id, node) } for (let node of nodes) { const fragments = node.path.split('/'); const parentId = fragments[fragments.length - 2]; const parent = index.get(parentId); if (parent !== undefined) { parent.children = parent.children || []; if (!parent.children.includes(node)) { parent.children.push(node); } } } // TODO: Decide which node is the root. // Here's one way to get the first (possibly only) root. const root = index.get(nodes[0].path.split('/')[0]); console.dir(root, { depth: null });

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

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