5

I pass this list from python to javascript like this:

 var string=["test_data/new_directory/ok.txt","test_data/reads_1.fq","test_data/test_ref.fa"];

I want output like this:

test_data
  reads_1.fq
  test_ref.fa
  new_directory
    ok.txt

Or also the output could be like this:

test_data
 reads_1.fq
 test_ref.fa

test_data/new_directory
  ok.txt

I used split function to get a list with each file and directory like this:

var string=["test_data/new_directory/ok.txt","test_data/reads_1.fq","test_data/test_ref.fa"];

                                     for(var i=0;i<string.length;i++){

                                         var result = string[i].split('/');

                                          console.log(result);


                                     }

Output looks like this:

["test_data", "new_directory", "ok.txt"]
["test_data", "reads_1.fq"]
["test_data", "test_ref.fa"]

How can I convert into the format I showed above? Thanks

6
  • 1
    Nice one. Working on it. :) Commented Jun 17, 2013 at 5:06
  • I guess if I convert the string into JSON, it works. :) Commented Jun 17, 2013 at 5:08
  • Yes, I don't mind using JSON if it works. Commented Jun 17, 2013 at 5:09
  • Not working: jsfiddle.net/praveenscience/yMY6b Tried my best! :( Commented Jun 17, 2013 at 5:17
  • 1
    @PraveenKumar please see my updated question with the optional output. Do you think that kind of output can be achieved? Thanks Commented Jun 17, 2013 at 5:49

2 Answers 2

6

Sorry for being late to the party. I ran into a similar issue trying to break out a list of paths into a nested object. Here's a fiddle showing how I ended up doing it.

var list = [];
list.push("A/B/C");
list.push("A/B/D");
list.push("A/B/C");
list.push("B/D/E");
list.push("D/B/E");
list.push("A/D/C");

var data = [];
for(var i = 0 ; i< list.length; i++)
{
   buildTree(list[i].split('/'),data);    
}
debugger;

function buildTree(parts,treeNode) {
     if(parts.length === 0)
     {
          return; 
     }

     for(var i = 0 ; i < treeNode.length; i++)
     {
          if(parts[0] == treeNode[i].text)
          {
              buildTree(parts.splice(1,parts.length),treeNode[i].children);
              return;
          }
     }

     var newNode = {'text': parts[0] ,'children':[]};
     treeNode.push(newNode);
     buildTree(parts.splice(1,parts.length),newNode.children);
}

https://jsfiddle.net/z07q8omt/

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

1 Comment

Thank you for posting an answer to SO. Please consider editing your answer to provide more context for your answer's code. Also, please consider incorporating your url at the end of your post into text that explains why you have included it as part of the post.
4

That's certainly possible, but it requires recursion.

The first thing you'll want to do (as you've already figured out to do, in fact) is split on the slashes. We'll use map for simplicity:

paths = paths.map(function(path) { return path.split('/'); });

Now we'll want to convert this into an array of objects with name and children properties. This means we'll have to use recursion.

In this function, we'll do a first pass grouping them by their first element:

var items = [];
for(var i = 0, l = paths.length; i < l; i++) {
    var path = paths[i];
    var name = path[0];
    var rest = path.slice(1);
    var item = null;
    for(var j = 0, m = items.length; j < m; j++) {
        if(items[j].name === name) {
            item = items[j];
            break;
        }
    }
    if(item === null) {
        item = {name: name, children: []};
        items.push(item);
    }
    if(rest.length > 0) {
        item.children.push(rest);
    }
}

Then we can recurse on all of these (assuming the function name we chose was structurize):

for(i = 0, l = items.length; i < l; i++) {
    item = items[i];
    item.children = structurize(item.children);
}

Now we've got a nice structure. We can then stringify it, again with a recursive function. Since the directory listing is just each item name followed by the indented directory contents listing, we can write that fairly easily:

function stringify(items) {
    var lines = [];
    for(var i = 0, l = items.length; i < l; i++) {
        var item = items[i];
        lines.push(item.name);
        var subLines = stringify(item.children);
        for(var j = 0, m = subLines.length; j < m; j++) {
            lines.push("  " + subLines[j]);
        }
    }
    return lines;
}

Then, to actually do it:

console.log(stringify(structurize(paths)).join("\n"));

9 Comments

Thank you so much for the wonderful answer. +1. But I got this error while calling console.log at last: RangeError: Maximum call stack size exceeded
@user2032220: I had a small bug; item.children.push(rest); should only happen if rest.length > 0. See my edited answer.
I am still newbie to javascript. Now, I have having problem with structuring your code. I have put the second code snippet in a function called structurize() and loop the third piece of code then I got items not defined. What does the items indicate in the for loop?
I managed code to bind in the proper structure. Finally, I get : TypeError: Cannot read property 'length' of undefined
@user2032220: The code is all together in the working example I linked to.
|

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.