Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

212
Views
convert list of strings to recursive/nested dict/json object (file explorer type system)

I have a Redux Store that is currently returning me a list of strings that represent folders example below"

/Documents/Pictures/Test

/Documents/Pictures/Test2

/System

/Libraries/Node

and I would like to cover this to a dict/json object in javascript so that it looks like:

data = {        id:'0',
        name:"/",
        child:[{
              id:'1',
              name:"Documents",
              child:[
                id:'2',
                name:"Pictures",
                child:[{
                  id:'3',
                  name:"Test",
                  child:[]
                },
                {
                  id:'3',
                  name:"Test2",
                  child:[]
                }]
                ]},
              id:'1',
              name:"System",
              child:[]
              
              
              ]}
.... so on and so forth

I have spent two days on this, and I have played around with using Object.keys but can't seem to get it to work and matching but can't seem to get it to work.

this is my current code that "works" but does not do it recursively

convertThePaths(){
    var pathRow = this.props.paths[0]; //grabbing the first array to test (/documents/pictures/test) is in here
    
    pathArray = pathRow.split("/") //splits between the /'s to get folder names
    
    var data = { id:'0',name:"/",child:[]}
    for (var j = 0; pathArray.length;j++){
      data.child.push(
      id: j
      name: pathArray[j],
      child: [] // need recursive here? maybe call convertPaths?
      )
}

id does not matter as long as its unique, I know how to do this in python but not javascript. any help is appreciated! I feel like I am over complicating this...

about 4 years ago · Juan Pablo Isaza
3 answers
Answer question

0

Here's how to do it below. I explain with code comments

const convertThePaths = (pathRows,data,index)=>{
    // Once index is the size of the pathRows were done
    if (pathRows.length===index){
        return;
    }
    
   let pathArray = pathRows[index].split("/"); //splits between the /'s to get folder names
   pathArray = pathArray.slice(1,pathArray.length); // remove empty string at start of arr.

   // Cur depth of dictionary
   let curData = data; 
   // Loop through all paths in pathArray
   for (const pathName of pathArray){
       // Filter for the pathName in the children 
       let childInlst = curData["child"].filter(obj=>obj.name===pathName);
       
       // If list is empty no such child was found so add it 
       if (childInlst.length===0){
           // Add child that doesn't exist yet
           curData["child"].push({
               "name":pathName,
               "id":`${parseInt(curData["id"])+1}`,
               "child":[],
           })
       }
       // Now child must exist so filter it and it will be index 0 of the list 
       curData = curData["child"].filter(obj=>obj.name===pathName)[0];

       // Then repeat
   }
    
    // Now repeat the same step with the next path in pathRows
    convertThePaths(pathRows,data,index+1);
}
 
// Prints out the data recursively
const printData = (data)=>{
    console.log(data.name+" "+data.id);
    if (data.child.length===0){
        return;
    }
    for (const child of data.child){
        printData(child)
    }
}


const Main=()=>{
    const pathRows = [
       "/Documents/Pictures/Test",
       "/Documents/Pictures/Test2",
       "/System",
       "/Libraries/Node",
    ]
    
    // Data start state
    const data = {"id":"0","name":"/","child":[]};
    
    // Recursive function
    convertThePaths(pathRows,data,0);
    
    // function to print data out recursively
    printData(data);
    
    
    
}

Main();

Output printed out recursively

/ 0
Documents 1
Pictures 2
Test 3
Test2 3
System 1
Libraries 1
Node 2
about 4 years ago · Juan Pablo Isaza Report

0

Here's an approach based on a fairly generic function I've used elsewhere:

const setPath = ([p, ...ps], id = 0) => (v) => (o) =>
  p == undefined ? v : Object .assign (
    Array .isArray (o) || Number .isInteger (p) ? [] : {},
    {...o, [p]: setPath (ps, id + 1) (v) ((o || {}) [p])},
  )

const expand = (o, id = 0) => 
  Object .entries (o) .map (([name, v]) => ({id, name, child: expand (v, id + 1)}))

const transform = (ps) => 
  expand (
    ps .map (p => ['/', ...p .slice (1) .split ('/')])
       .reduce ((a, p) => setPath (p) ({}) (a), {})
  ) [0]

const paths = ['/Documents/Pictures/Test', '/Documents/Pictures/Test2', '/System', '/Libraries/Node']

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

The generic utility function setPath accepts a path such as ['foo', 'bar', 'baz'], then a value such as 42, and finally an object like {foo : {qux: 100, corge: 200}), and returns an object like {foo : {qux: 100, corge: 200, bar: {baz: 42}). If intermediate paths are missing, it creates them: arrays if the path node is an integer, objects otherwise.

The main function is transform, which

  1. takes your array of entries such as '/Documents/Pictures/Test', and turns each into something like ['/', 'Documents', 'Pictures', 'Test'] We intentionally add an extra / in the beginning of each result to account for the eventual root node nor clearly present in the original.

  2. folds setPath over these results, passing an empty object in for every value, returning something like {"/": {Documents: {Pictures: {Test: {}, Test2: {}}}, System: {}, Libraries: {Node: {}}}}

  3. Calls the expand helper, which (recursively) turns that (almost) into the structure you're looking for, just wrapped in an array, since the recursion needs to work on an array of children.

  4. Pulls of the first value from the returned array to give you the final result.

I find this sort of transformation, as a series of distinct steps much easier to think about, and as each one is fairly simple, the whole thing can become easier to write.

about 4 years ago · Juan Pablo Isaza Report

0

Some what like this:


function getMyData(list) {
  const data = { id: "0", name: "/", child: [] };
  for (let a = 0; a < list.length; a++) {
    const pathArray = list[a].split("/").splice(1);
    if (pathArray.length) {
      for (let i = 0; i < pathArray.length; i++) {
        const subChild = {
          id: (i + 1).toString(),
          name: pathArray[i],
          child: [],
        };
        data.child.push(subChild);

        if (pathArray.length > i) {
          const currentChildIndex = data.child.findIndex(
            (x) => x.name === pathArray[i]
          );
          const newObj = {
            id: (i + 2).toString(),
            name: pathArray[i + 1],
            child: [],
          };
          if (currentChildIndex === 0 || currentChildIndex) {
            data.child[currentChildIndex].child.push(newObj);
          }
        }
        pathArray.splice(i);
      }
    }
  }

  return data;
}

console.log(getMyData(arr));

But I thought there might have a better way

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!