Home > Blockchain >  generate tree-like structure using dot-separated string
generate tree-like structure using dot-separated string

Time:04-27

I struggle with tree structure. :(

I would like to make a tree following the below interface.

export type Tree = Array<TreeNode>;

export interface TreeNode {
  label: string;
  type: 'folder' | 'file';
  children: Array<TreeNode> | string;
}

For example,

I have a JSON file like this

{
  "common.header.title": "Header Title",
  "common.footer.btn": "Footer button",
  "common.footer.btn.submit": "Footer Submit",
  "apage.title": "apage Title"
}

My expected output is like this.

const out = [
  {
    label: 'apage',
    type: 'folder',
    children: [
      { label: 'title', type: 'file', children: 'apage Title' }
    ]
  }, {
    label: 'common',
    type: 'folder',
    children: [
      {
        label: 'footer', 
        type: 'folder', 
        children: [
          { label: 'btn', type: 'file', children: 'Footer button' },
          {
            label: 'btn', 
            type: 'folder', 
            children: [{ label: 'submit', type: 'file', children: 'Footer Submit' }] 
          },
        ]
      }, {
        label: 'header',
        type: 'folder',
        children: [{ label: 'title', type: 'file', children: 'Header Title' }]
      }
    ]
  }
]

I've seen some similar cases in SO, but I couldn't refer and develop with that cases.

CodePudding user response:

You could search for the wanted labels and check if children is an array, then use this object for searchin in the nested array.

Finally push a new object.

const
    data = { "common.header.title": "Header Title", "common.footer.btn": "Footer button", "common.footer.btn.submit": "Footer Submit", "apage.title": "apage Title" },
    result = Object
        .entries(data)
        .sort(([a], [b]) => a.localeCompare(b))
        .reduce((r, [path, children]) => {
            const 
                keys = path.split('.'),
                label = keys.pop();
                
            keys
                .reduce((t, label) => {
                    let temp = t.find(o => o.label === label && Array.isArray(o.children));
                    if (!temp) t.push(temp = { label, type: 'folder', children: [] });
                    return temp.children;
                }, r)
                .push({ label, type: 'file', children });

            return r;
        }, []);

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

  • Related