2016-02-18 112 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>');