1

How do I build a JSON object thats is compatible with react-sortable-tree (every nested object has title, children) to render the file tree.

For example, I have this array of filepaths.

var filePaths = [
   "Diagnoses/Endocrine disorders/Thyroid disorders/Congenital hypothyroidism",
   "Diagnoses/Endocrine disorders/Thyroid disorders/Acquired hypothyroidism",
   "Diagnoses/Endocrine disorders/Thyroid disorders/Acquired hypothyroidism/Postsurgical hypothyroidism"
];

I would like a JSON Object like this.

var treeData = [
  {
    title: 'Diagnoses',
    children: [{
      title: 'Endocrine disorders',
      children: [{
        title: 'Thyroid disorders',
        children: [
        {
          title: 'Congential hypothyroidism'
        },
        {
          title: 'Acquired hypothyroidism',
          children: [{
            title: 'Postsurgical hypothyroidism'
          }]
        }
        ]
      }]
    }]
  }
];

Edit: I tried this but after the first iteration, I'm overwriting the children property of the whole tree. I tried a couple of checks to stop that but they didn't quite pan out.

var hierarchy = filePaths.reduce(function(hier,path){
    var x = hier;
    path.split('/').forEach(function(item, index, array){
        if(x[0].title != item){
            x[0].title = item;
        }
        // console.log(index, array.length)
        if (index != array.length - 1 && !x[0].children){
          x[0].children = [{
            title: ''
          }];
        }
        x = x[0].children;
    });

    return hier;
}, [{title: ''}]);
schintha
  • 15
  • 1
  • 4

1 Answers1

4

I think the main issue with your code is that you're not walking down the tree to insert nodes at the right place.

I took a two-step approach, since I didn't like the idea of iterating through a list of children each time when a dictionary lookup would be faster.

See the comments in the code for an explanation of what's going on:

var filePaths = [
  "Diagnoses/Endocrine disorders/Thyroid disorders/Congenital hypothyroidism",
  "Diagnoses/Endocrine disorders/Thyroid disorders/Acquired hypothyroidism",
  "Diagnoses/Endocrine disorders/Thyroid disorders/Acquired hypothyroidism/Postsurgical hypothyroidism"
];

// Step 1:
// Convert the flat list of paths to nested dictionaries.
// (This representation is more efficient for the initial construction.)
// Basic algorithm:
// 1. Split each path into segments.
// 2. Walk down the tree using the segments as keys.
// 3. Create new nodes as necessary.

var tree = {};
filePaths.forEach(function (path) {
  var currentNode = tree;
  path.split('/').forEach(function (segment) {
    if (currentNode[segment] === undefined) {
      currentNode[segment] = {};
    }
    currentNode = currentNode[segment];
  });
});

// Now we have a tree represented as nested dictionaries.
console.log(JSON.stringify(tree, null, 2));

// {
//   "Diagnoses": {
//     "Endocrine disorders": {
//       "Thyroid disorders": {
//         "Congenital hypothyroidism": {},
//         "Acquired hypothyroidism": {
//           "Postsurgical hypothyroidism": {}
//         }
//       }
//     }
//   }
// }

// Step 2:
// Convert the nested dictionaries into lists of children.
// This is the format required for react-sortable-tree.
// Basic algorithm:
// 1. Each dictionary becomes an array of children.
// 2. Each element of the array has a title and a list of children.
// 3. We recurse for the list of children (if we have children).
function toTreeData(tree) {
  return Object.keys(tree).map(function (title) {
    var o = { title: title };
    if (Object.keys(tree[title]).length > 0) {
      o.children = toTreeData(tree[title]);
    }

    return o;
  });
}

console.log(JSON.stringify(toTreeData(tree), null, 2));

// [
//   {
//     "title": "Diagnoses",
//     "children": [
//       {
//         "title": "Endocrine disorders",
//         "children": [
//           {
//             "title": "Thyroid disorders",
//             "children": [
//               {
//                 "title": "Congenital hypothyroidism"
//               },
//               {
//                 "title": "Acquired hypothyroidism",
//                 "children": [
//                   {
//                     "title": "Postsurgical hypothyroidism"
//                   }
//                 ]
//               }
//             ]
//           }
//         ]
//       }
//     ]
//   }
// ]
user94559
  • 59,196
  • 6
  • 103
  • 103
  • Thank you! I knew that iterating through the children every time was not the right way. And I was more sure when I saw myself writing small checks to avoid little things. Really appreciate the explanations! :) – schintha Jul 07 '17 at 18:14