2014-02-13 3 views
2

Я пытаюсь создать URL-адреса для страниц, хранящихся в MongoDB в узле.Обход дерева в javascript

Используя следующую функцию, я хочу пройти объект javascript и отобразить путь к каждому элементу.

Я почти там, но я застрял - может быть, даже лучший способ сделать это, используя Async (что я должен признать, меня немного смущает).

Функция: (demo)

function printTree(people, slug) { 
    for (var p = 0; p < people.length; p++) { 
     var root = people[p]; 
     slug = slug + root.name + "/"; 
     console.log(slug); 
     if (root.children.length > 0) { 
      var childrenCount = root.children.length; 
      for (var c = 0; c < childrenCount; c++) { 
       if (root.children[c].children.length > 0) { 
        printTree(root.children[c].children, slug + root.children[c].name + "/"); 
       } 
      } 
     } 
    } 
}; 

Выход:

/michael/ 
/michael/angela/oscar 
/michael/meredith/creed 
/michael/meredith/creed/kelly 

Ожидаемый результат:

/michael/ 
/michael/angela/ 
/michael/angela/oscar/ 
/michael/meredith/ 
/michael/meredith/creed/ 
/michael/meredith/kelly/ 

Объект:

[ 
    { 
    "name": "michael", 
    ... 
    "children": [ 
     { 
     "name": "angela", 
     ... 
     "children": [ 
      { 
      "name": "oscar", 
      ... 
      "children": [] 
      } 
     ] 
     }, 
     { 
     "name": "meredith", 
     ... 
     "children": [ 
      { 
      "name": "creed", 
      ... 
      "children": [] 
      }, 
      { 
      "name": "kelly", 
      ... 
      "children": [] 
      } 
     ] 
     }, 
     { ... } 
    ] 
    } 
] 

Если это поможет, то данные сохраняются с помощью вложенных наборов: https://github.com/groupdock/mongoose-nested-set Так что может быть лучше сделать выше работу, используя вложенные наборы (отрицающие вышеупомянутую объекта).

ответ

5

Здесь вы идете. Вам не нужен второй цикл for, так как ваша функция printTree все равно будет проходить через все (demo).

function printTree(people, slug){ 
    slug = slug || '/'; 
    for(var i = 0; i < people.length; i++) { 
    console.log(slug + people[i].name + '/'); 
    if(people[i].children.length){ 
     printTree(people[i].children, slug + people[i].name + '/') 
    } 
    } 
} 
+0

Вы абсолютно прибил его! http://jsfiddle.net/cT8wn/2/ –

+0

Привет, это работает для майкла, ангелы и оскара, но как только дерево попадает к другим детям Майкла, он ломается. [см. демонстрацию] (http://jsfiddle.net/WHZUE/) meredith является братом ангелы, но на выходе появляется меридит как ребенок ангелы. – logikal

+0

Это из-за этой строки: 'slug = slug + people [i] .name + '/';' исправлено это для вас –

1

Вы также могли бы рассмотреть что-то в ECMA5, как это, в случае, если у вас есть дальнейшее использование tree или хотите использовать некоторые Seperator кроме /. Ничего плохого в ответе @bioball, это просто дает вам больше гибкости, если захочет.

function makeTree(people, slug, sep) { 
    slug = slug || '/'; 
    sep = sep || slug; 
    return people.reduce(function (tree, person) { 
     var slugPerson = slug + person.name + sep; 

     return tree.concat(slugPerson, makeTree(person.children, slugPerson, sep)); 
    }, []); 
} 

function printTree(tree) { 
    tree.forEach(function (path) { 
     console.log(path); 
    }); 
} 

printTree(makeTree(data)); 

На jsFiddle

+0

Это приятное решение! было бы проще изменить этот метод, чтобы создать путь к человеку? IE: Учитывая «Келли» и дерево, сгенерируйте/michael/meredith/kelly? В настоящее время я пытаюсь обратить вспять фантастический @bioball и Джейсон, чтобы сделать это, но я терплю неудачу. – logikal

+0

Звучит как еще один вопрос, который вы должны создать здесь, на SO, и, возможно, вы заработаете еще немного репутации за хороший вопрос. Но, возможно, вы имеете в виду, как в этом [jsFiddle] (http://jsfiddle.net/Xotic750/wwDmJ/)? Конечно, вы можете изменить фильтр, чтобы делать все, что хотите. Я привел два примера. – Xotic750

Смежные вопросы