0

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\
4
  • 5
    And whats wrong with the code you have? Commented Sep 1, 2019 at 9:26
  • Because he'd have to manually input the maximum number of levels of depth. I'd probably aim to do this recursively although I am not sure how I'd deal with the different levels of indent. Commented Sep 1, 2019 at 9:39
  • 2
    @MatthewPlayer His code is already recursive. Commented Sep 1, 2019 at 9:44
  • 1
    The only difference I see is that of extra level of indent where at the root level you have \. Is that the only problem? Commented Sep 1, 2019 at 9:45

2 Answers 2

1

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(''))

Sign up to request clarification or add additional context in comments.

Comments

0

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));

2 Comments

I mean, handle it in another way
I think your method is good, I just shortened it in an edit a bit.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.