Cos'è un modo elegante e OOP per creare un albero dagli array e renderlo come un UL annidato

3

Ho una serie di matrici che rappresentano i percorsi del file system, quindi ogni valore successivo è in realtà una directory più profonda, ad esempio:

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

è l'equivalente di

Desktop
|-Pictures
  |-Summer 2011

Sto cercando un modo elegante per:

  1. Appiattisci / unisci tutti i diversi array che devo creare con un oggetto / dizionario / array multidimensionale.

  2. Analizza il risultato e rendi nidificato UL (elenco html) alla pagina che rappresenta correttamente la gerarchia.

  3. Scrivi ciò che ho già in un modo più "OOP" ..

Ho già una versione funzionante:

<!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>

Grazie!

EDIT: Sto iniziando dalle stringhe che rappresentano i percorsi, vale a dire "Desktop/Pictures/Summer 2011" , che sono danneggiati dagli array.

    
posta Amit 24.12.2011 - 22:59
fonte

3 risposte

1

In un semplice modo OO - definirei tutte le vars - a, b, c, and d stesso come un albero.

a_tree = new tree(a); 

e lo stesso per tutti gli altri. Dopo avrò avuto un comando di fusione albero

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

Questo è solo un altro modo di fare le cose. Tipicamente merge_tree dovrebbe essere un processo ricorsivo.

Penso che giudicare quale metodo abbia una differenza più significativa del tutto, quando ridimensiona l'albero a grandi dimensioni.

    
risposta data 25.12.2011 - 05:11
fonte
0

È necessario modellare un nodo di classe che abbia una variabile a e che possa puntare a se stesso e quindi utilizzare DFS per cercare l'albero. Nel tuo esempio utilizzi un elenco adiacente che non è in realtà uno stile orientato agli oggetti. La radice dell'albero è un caso speciale in cui la variabile a è un numero magico.

    
risposta data 25.12.2011 - 10:30
fonte
0

Ho trovato questa una soluzione molto bella per la creazione di un albero. Per essere più OO, ho creato un componente Tree e la parte base di questo è diventata uno dei suoi metodi. Sembra esserci un piccolo difetto nella funzione createList. Se un nodo secondario ha lo stesso nome di un nodo superiore, apparirà come nodo superiore.

L'ho risolto in questo modo, che sfrutta al massimo l'azione ricorsiva mentre passo ad aggiungere a:

            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 );
                }
            }
    
risposta data 05.05.2014 - 22:15
fonte

Leggi altre domande sui tag