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