2012-01-14 3 views
3

Я был на этом весь день, пытаясь написать рекурсивную функцию в Javascript, чтобы получить размеры. Мне нужна помощь:/Как получить размер объекта JSON различной глубины в javascript?

В принципе, мой объект JSON содержит иерархические категории/подкатегории. Я хотел бы определить размер каждой категории/подкатегории.

Вот простая демонстрация: http://pastehtml.com/view/bkpzzlabs.html

Я хотел бы взять JSON на левой и получить HTML справа. Возможно, я слишком долго смотрел на этот компьютерный монитор, потому что для жизни я не могу понять это.

Большое спасибо за помощь.

+0

У вас есть код вообще? Пожалуйста, покажите, что у вас есть. – Hogan

+0

@Hogan http://codepad.org/Wjlr1rJW –

ответ

3

Правая часть вашей «демонстрации» предполагает, что вы не просто хотите рекурсивно подсчитать общее количество конечных точек (или «листьев») в вашем JSON; вы хотите знать рекурсивный размер для каждой категории (нелистовой узел) в дереве. Ключ здесь состоит в том, что узлы между листьями и корнем не учитываются.

Обновление: Я обновил функцию; читай ниже.

Попробуйте это:

function parseTree(parent) { 
    var hasNonLeafNodes = false; 
    var childCount = 0; 

    for (var child in parent) { 
     if (typeof parent[child] === 'object') { 
      // Parse this sub-category: 
      childCount += parseTree(parent[child]); 
      // Set the hasNonLeafNodes flag (used below): 
      hasNonLeafNodes = true; 
     } 
    } 

    if (hasNonLeafNodes) { 
     // Add 'num_children' element and return the recursive result: 
     parent.num_children = childCount; 
     return childCount; 
    } else { 
     // This is a leaf item, so return 1: 
     return 1; 
    } 
} 

Эта функция изменить исходный объект, так что новый ключ 'num_children' добавляется к каждому узлу без листьев в дереве. Функция возвращает общее количество листовых узлов во всех потомках parent. Обратите внимание, что также можно вызвать эту функцию на подмножестве вашего объекта.

Вот демо: http://jsfiddle.net/PPvG/CXXaB/

К сожалению об этом! Мне пришлось немного поработать и, по-видимому, забыл, что это я делал здесь ... ;-)

Обновленное решение должно правильно считать адреса, но имейте в виду, что массивы не могут иметь (например, num_children). Это важно в вашем примере, например. «Pothole» - это массив.

+0

Спасибо, что нашли время, чтобы написать это! Похоже, что значение num_children на самом деле _double_, что это должно быть, но я просматриваю теперь, чтобы проверить, могу ли я это исправить. –

+0

@Tobias: oops, извините! Там был небольшой пробел в мозге. См. Мое обновление. :-) – PPvG

+0

Фантастический! Вы знаете, как заставить его делать подсчеты для массивов? Например, он не дает num_children для «Pothole», потому что это [] массив, но он будет считать «Заброшенное здание», потому что это объект {}. –

0

Вопрос неясный. Я думаю, что вам нужно что-то подобное глубокой комедии. Следующее - функция для глубокой кишки.

function deepCopy(p) { 
    var c = {}; 
    for (var i in p) { 
      if (typeof p[i] === 'object') { 
      c[i] = (p[i].constructor === Array)?[]:{}; 
      deepCopy(p[i],c[i]); 
      } 
    else { 
      c[i] = p[i]; 
      } 
    } 
    return c; 
    } 

Настройте вышеуказанную функцию глубокой печати для вашего приложения.

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