3

I have a series of arrays which represent file system paths, so each next value is actually a directory deeper, for example:

var a1 = ["Desktop", "Pictures", "Summer 2011"];

is the equivalent of

Desktop
|-Pictures
  |-Summer 2011

I'm trying to find an elegant way to:

  1. Flatten/merge all the different arrays I have to come up with one object/dictionary/multi-dimensional-array.

  2. Parse the result and render a nested UL (html list) to the page which represents the hierarchy correctly.

  3. Write what I already have in a more 'OOP way'..

I already have a working version:

<!DOCTYPE html>
<html>
    <head></head>
    <body onload="init()">
        <ul id="tree"></ul>
        <script>
            var a = [ "Desktop", "Folder1",  "InnerFolder1" ];
            var b = [ "Desktop", "Folder1",  "Inner 2" ];
            var c = [ "Documents", "Folder 2", "InnerFolder1", "even deepper" ];
            var d = [ "Something Else", "Folder1",  "Inner 2" ];

            var all = [a, b, c, d];
            var Tree = {};
            var ul = document.getElementById("tree");

            function init(){
                for ( var i = 0; i < all.length; i++ ){
                    addToTree(Tree, all[i] );
                }
                createList(Tree, ul);
            }

            //function from http://stackoverflow.com/questions/3663096/how-to-convert-array-to-tree
            function addToTree(tree, array) {
                for (var i = 0, length = array.length; i < length; i++) {
                    tree = tree[ array[i] ] = tree[ array[i] ] || {};
                }
            }

            function createList( obj, _pushTo  ){
                for ( attr in obj ){
                    var _doIHaveChildren = function ( ){
                        for(var prop in obj[attr]) {
                            if (obj[attr].hasOwnProperty(prop)) {
                                return true;
                            }
                        }
                        return false;
                    }
                    var li = document.createElement("li");
                    li.id = attr.toString();
                    li.innerHTML = attr.toString();
                    if ( Tree.hasOwnProperty(attr) ){
                        ul.appendChild(li);
                    } else {
                        _pushTo.appendChild(li);
                    }
                    if ( _doIHaveChildren() === true ){
                        var ul2 = document.createElement("ul");
                        li.appendChild(ul2);
                    }
                    createList( obj[attr], ul2 );
                }
            }
        </script>
    </body>
</html>

Thanks!

EDIT: I'm starting from strings which represent the paths i.e. "Desktop/Pictures/Summer 2011" which are broken to arrays.

1
  • 1
    When it comes to the algorithms and data structures, "elegant" and "OOP" cannot be used together in the same sentence. OOP simply should not be used for such things.
    – SK-logic
    Dec 26, 2011 at 13:02

3 Answers 3

1

In a simple OO way - i would define all the vars - a, b, c, and d itself as a tree.

a_tree = new tree(a); 

and same for all others. After that i would have have a merge tree command

a_tree.merge_tree(b);
a_tree.merge_tree(c); 

This is just another way to do things. Typically merge_tree should be recursive process.

I think to judge which method has more significant different at all, when you scale up the tree to a large size.

0

You need to model a class node that has a variable a and that can points to itself and then you can use DFS to search the tree. In your example you use an adjacent list which isn't really object oriented style. The root of the tree is a special case where the variable a is a magic number.

0

I found this to be a very nice solution to creating a tree. To be more OO, I created a Tree component and the basic part of this became one of its methods. There seems to be a small flaw in the createList function. If a sub node has the same name as a top node, it will appear as a top node.

I fixed it this way, which also takes greater advantage of the recursive action while passing the to append to:

            function createList( obj, _pushTo  ){
                var ul2;
                for ( attr in obj ){
                    var _doIHaveChildren = function ( ){
                        for(var prop in obj[attr]) {
                            if (obj[attr].hasOwnProperty(prop)) {
                                return true;
                            }
                        }
                        return false;
                    }
                    var li = document.createElement("li");
                    li.id = attr.toString();
                    li.innerHTML = attr.toString();
                    _pushTo.appendChild(li);
                    if ( _doIHaveChildren() === true ){
                        ul2 = document.createElement("ul");
                        li.appendChild(ul2);
                    }//else return
                    createList( obj[attr], ul2 );
                }
            }

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.