Array to tree structure

Viewed 54
[
    [
        "zhejiang",
        "hangzhou2"
    ],
    [
        "zhejiang",
        "hangzhou",
        "a",
        "a1"
    ],
    [
        "jiangsu",
        "nanjing",
        "zhonghuamen"
    ],
    [
        "zhejiang",
        "hangzhou",
        "a",
        "a2"
    ],
    [
        "zhejiang",
        "hangzhou",
        "a",
        "a3"
    ]
]

Hi everyone, im using ant design's cascader and it returns selected values in array structure like above.

As you can see, each value is the parent of the subsequent value. I need to convert above structure to the below structure, so i can use it in antdesign's tree component. I tried so many ways but i just couldn't do it.

[
       {
          "title":"zhejiang",
          "key":"zhejiang",
          "children":[
             {  
                "title":"hangzhou2",
                "key":"hangzhou2"
             },
             {
                "title":"hangzhou",
                "key":"hangzhou",
                "children":[
                   {
                      "title":"a",
                      "key":"a",
                      "children":[
                         {
                            "title":"a1",
                            "key":"a1"
                         },
                         {
                            "title":"a2",
                            "key":"a2"
                         },
                         {
                            "title":"a3",
                            "key":"a3"
                         }
                      ]
                   }
                ]
             },
          ]
       },
       {
          "title":"jiangsu",
          "key":"jiangsu",
          "children":[
             {  
                "title":"hangzhou2",
                "key":"hangzhou2"
             },
             {
                "title":"nanjing",
                "key":"nanjing",
                "children":[
                   {
                      "title":"zhonghuamen",
                      "key":"zhonghuamen",
                   }
                ]
             },
          ]
       }
    ]
2 Answers

You could iterate the path of titles and build an object if not exist.

const
    data = [["zhejiang", "hangzhou2"], ["zhejiang", "hangzhou", "a", "a1"], ["jiangsu", "nanjing", "zhonghuamen"], ["zhejiang", "hangzhou", "a", "a2"], ["zhejiang", "hangzhou", "a", "a3"]],
    result = data.reduce((children, path) => {
          path.reduce((object, title) => {
              let item = (object.children ??= []).find(q => q.title === title);
              if (!item) object.children.push(item = { title, key: title });
              return item;
          }, { children });
          return children;
      }, []);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Collect all paths with the same prefix, then generate subtree for that prefix:

function treeify(items) {
  const lookup = {};
  for (const item of items) {
    if (item.length) {
      const [first, ...rest] = item;
      (lookup[first] ??= []).push(rest);
    }
  }
  return Object.keys(lookup).map(key => {
    const node = { title: key, key };
    const children = treeify(lookup[key]);
    if (children.length) node.children = children;
    return node;
  });
}

const items = [["zhejiang","hangzhou2"],["zhejiang","hangzhou","a","a1"],["jiangsu","nanjing","zhonghuamen"],["zhejiang","hangzhou","a","a2"],["zhejiang","hangzhou","a","a3"]];
const tree = treeify(items);
console.log(tree);

Related