How to get a string path from array-like object

I'm attempting to build a string path from array-like object. But my solution is not good

// in cay thu muc
var test = [
  {
    name: "home",
    children: [
      {
        name: "dev",
        children: [
          {
            name: "ahihi.txt"
          },
          {
            name: "hhh.js"
          }
        ]
      }
    ]
  },
  {
    name: "www",
    children: [
      {
        name: "fol1",
        children: [
          {
            name: "fdsafd"
          }
        ]
      },
      {
        name: "fol3",
        children: []
      }
    ]
  },
  {
    name: "fol2",
    children: []
  }
];

function printChild(items, tabNum) {
  let indent = `${"  ".repeat(tabNum)}`;
  let child = "";

  [...items].forEach(item => {
    if (!item.hasOwnProperty("children")) {
      child += `${indent + item.name}\n`;
    } else if (item.children.length === 0) {
      child += `${indent + item.name}\\\n`;
    } else {
      child += `${indent +
        item.name +
        "\\\n" +
        printChild(item.children, tabNum + 1)}`;
    }
  });

  return child;
}

function tree(test) {
  let res = `\\\n${printChild(test, 1)}`;
  return res;
}

console.log(tree(test));

Here's repl link: https://repl.it/repls/CrispRashHack

Ideally, this should result in something like;

  home\
    dev\
      ahihi.txt
      hhh.js
  www\
    fol1\
      fdsafd
    fol3\
  fol2\

Upvotes: 0

Views: 214

Answers (2)

Volper
Volper

Reputation: 684

Looks like your code works. I don't know what you mean by "my solution is not good".

If you just want to remove the backslash at the beggining (to make it the same as in the expected result you posted), change the line:

let res = `\\\n${printChild(test, 1)}`;

to:

let res = printChild(test, 0);

Also, you do not need the [...items] because it is an actual array and not only an array-like object, so just items will do.

Your code can be shortened as well:

function printChild(items, tabNum) {
  let indent = "  ".repeat(tabNum);
  let child = "";

  items.forEach(item => {
    child += indent + item.name;
    if (!item.hasOwnProperty("children")) {
      child += "\n";
    } else if (item.children === []) {
      child += "\\\n";
    } else {
      child += `\\\n${printChild(item.children, tabNum + 1)}`;
    }
  });

  return child;
}

console.log(printChild(test, 0));

Upvotes: 0

adiga
adiga

Reputation: 35242

You could use flatMap to get an array of string to be concatenated. Then use join to create the final string

var test=[{name:"home",children:[{name:"dev",children:[{name:"ahihi.txt"},{name:"hhh.js"}]}]},{name:"www",children:[{name:"fol1",children:[{name:"fdsafd"}]},{name:"fol3",children:[]}]},{name:"fol2",children:[]}];

function stringify(arr, index = 0) {
  const prefix = '   '.repeat(index);
  
  return arr.flatMap(o => 
    o.children 
      ? [`${prefix}${o.name}\\\n`, ...stringify(o.children, index + 1)]
      : `${prefix}${o.name}\n`
  )
}

console.log(stringify(test).join(''))

Upvotes: 1

Related Questions