2016-02-18 4 views
7

У меня есть массив, который выглядит примерно так:Javascript массив в объект

files = [ 
    'Dashboard/Logs/Errors', 
    'Dashboard/Logs/Other', 
    'Accounts/Main', 
] 

Я хочу, чтобы сделать его выглядеть следующим образом:

navigation = [ 
    { 
    "title": "Dashboard", 
    "dropdown": [ 
     { 
     "title": "Logs", 
     "dropdown": [ 
      { 
      "title": "Errors", 
      }, 
      { 
      "title": "Other", 
      } 
     ] 
     } 
    ] 
    }, 
    { 
    "title": "Accounts", 
    "dropdown": [ 
     { 
     "title": "Main", 
     } 
    ] 
    } 
] 

У меня есть следующий до сих пор:

var navigation = []; 
for (var i = 0; i < files.length; i++) { 
    var parts = files[i].split('/'); 
    navigation.push({title: parts[0]}); 
    for (var j = 1; j < parts.length; j++) { 

    } 
} 

У меня возникли трудности с выяснением достойного способа сделать это. То, что у меня до сих пор уже не работает, потому что оно создает два объекта под навигацией каждый с title: "Dashboard". Любые идеи для умного подхода? Спасибо :)

+0

Что навигации? 'navigation = [];'? – kulkarniankita

+0

@Alec Исправлена ​​ли глубина иерархии объектов? или есть максимальная глубина по крайней мере? – stark

+0

@ kulkarniankita «навигация» определяется прямо там. Конечным результатом должна быть «навигация». –

ответ

7

Это должно произвести желаемый результат:

var files = [ 
    'Dashboard/Logs/Errors', 
    'Dashboard/Logs/Other', 
    'Accounts/Main', 
]; 

var navigation = []; 
// Iterates through a navigation array and returns the object with matching title, if one exists. 
var getNavigationObject = function(nav, title) { 
    for (var i = 0; i < nav.length; i++) { 
    if (nav[i].title == title) { 
     return nav[i]; 
    } 
    } 
}; 
// Adds a file to the nav. 
// The input is an array of file components (i.e. file.split('/')) 
// This works by recursively adding each component of a file. 
var addToNav = function (nav, components) { 
    var n = getNavigationObject(nav, components[0]); 
    if (!n) { 
    n = { 
     title: components[0] 
    }; 
    nav.push(n); 
    } 
    if (components.length > 1) { 
    n.dropdown = n.dropdown || []; 
    addToNav(n.dropdown, components.slice(1)); 
    } 
}; 

// Actually call `addToNav` on each file. 
files.forEach(function(e) { 
    addToNav(navigation, e.split('/')); 
}); 

// Produces the result in string form. 
JSON.stringify(navigation, null, 2) 

Это работает рекурсивно проверить, является ли данный элемент уже соответствует компоненту файла. Если это так, оно повторяется в раскрывающемся списке этого компонента. В противном случае это создает.

+1

Уточненный. Написал это в спешке - конечно, не код уровня производства. :) – arcyqwerty

+0

Удивительно! –

1

Это подход с временным объектом и некоторыми методами массива без накладных расходов на поиск.

var files = ['Dashboard/Logs/Errors', 'Dashboard/Logs/Other', 'Accounts/Main'], 
 
    navigation = function (data) { 
 
     var r = [], o = {}; 
 
     data.forEach(function (a) { 
 
      var s = r; 
 
      a.split('/').reduce(function (p, b) { 
 
       if (p.children) { 
 
        p.value.dropdown = p.value.dropdown || []; 
 
        s = p.value.dropdown; 
 
        p = p.children; 
 
       } 
 
       if (!(b in p)) { 
 
        p[b] = { value: { title: b }, children: {} }; 
 
        s.push(p[b].value); 
 
       } 
 
       return p[b]; 
 
      }, o); 
 
     }); 
 
     return r; 
 
    }(files); 
 

 
document.write('<pre>' + JSON.stringify(navigation, 0, 4) + '</pre>');

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