2016-02-18 9 views
7

Mam tablicę, która wygląda tak:JavaScript Array do Object

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

Chcę, aby wyglądać tak:

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

mam następujące pory:

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++) { 

    } 
} 

Mam trudności z ustaleniem przyzwoitego sposobu na zrobienie tego. To, co do tej pory już nie działa, ponieważ tworzy dwa obiekty pod nawigacją, każdy z title: "Dashboard". Jakieś pomysły na sprytne podejście? Dzięki :)

+0

Jaka nawigacja? 'navigation = [];'? – kulkarniankita

+0

@Alec Czy ustalono głębokość hierarchii obiektów? lub czy istnieje maksymalna głębia? – stark

+0

"Nawigacja" zdefiniowana jest właśnie tam. Końcowym wynikiem powinna być "nawigacja". –

Odpowiedz

7

ta powinna wywołać pożądany wynik:

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) 

to działa rekurencyjnie przez sprawdzenie, czy dany element pasuje już komponent pliku. Jeśli tak, powraca do "listy rozwijanej" tego komponentu. W przeciwnym razie to tworzy.

+1

. Napisał to w pośpiechu - na pewno nie kod poziomu produkcji. :) – arcyqwerty

+0

Jesteś niesamowity !! –

1

Jest to podejście z tymczasowym obiektem i niektórymi metodami bez użycia przeszukiwania.

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>');