2016-10-01 49 views
1

总之对象的数组,我要创建一个通用方法“组织”关闭此:的Javascript,提取和组织由属性

[ 
    { name: 'band1', type: 'concert', subtype: 'rock' }, 
    { name: 'band2', type: 'concert', subtype: 'jazz' }, 
    { name: 'band3', type: 'concert', subtype: 'jazz' }, 
    { name: 'fun1', type: 'festival', subtype: 'beer' }, 
    { name: 'fun2', type: 'festival', subtype: 'food' }, 
] 

成这样:

{ 
    'concert': { 
     'rock': [ 
     { name: 'band1', type: 'concert', subtype: 'rock' }, 
     ], 
     'jazz': [ 
     { name: 'band2', type: 'concert', subtype: 'jazz' }, 
     { name: 'band3', type: 'concert', subtype: 'jazz' } 
     ] 
    }, 
    'festival': { 
     'beer': [ 
     { name: 'fun1', type: 'festival', subtype: 'beer' }, 
     ], 
     'food': [ 
     { name: 'fun2', type: 'festival', subtype: 'food' }, 
     ] 
    } 
} 

从签名:

organize(events, ['type', 'subtype']); 

我想这样做的原因是有一个简单的嵌套循环显示数据。如果你对Vue.js熟悉,它看起来像这样:

<div v-for="(type, subtypes) in organize(events, ['type', 'subtype'])"> 
    <h1>{{ type }}</h1> 
    <div v-for="(subtype, events) in subtypes"> 
    <h2>{{ subtype }}</h2> 
    <div v-for="event in events"> 
     <h3>{{ event.name }}</h3> 
    </div> 
    </div> 
</div> 

对我来说,这是一个大脑弯曲练习。我认为递归和mapfilterfilterreduce的一些组合已经成熟,但我花了太多时间试图想出解决方案,而是编写了一些非常难看的代码来完成基本相同的事情。这也可能,我不知道一些有用的功能的JavaScript,可以帮助我这样做...

建议或指导将不胜感激,但它不是一个紧迫的问题。我只是觉得有一个通用的方法来组织数组是非常有用的。

+0

只是一个建议:如果你已经有一个解决方案可行,但你认为可以进一步优化,你可以在[CodeReview](http://codereview.stackexchange.com)上发布一个问题;) – Terry

回答

2

我认为这可能是一个正确实施organize

function organize(rows, groupBy) { 
 
    var last = groupBy.length - 1; 
 
    return rows.reduce ((res, obj) => { 
 
     groupBy.reduce((res, grp, i) => 
 
      res[obj[grp]] || (res[obj[grp]] = i == last ? [] : {}), res).push(obj); 
 
     return res; 
 
    }, {}); 
 
} 
 

 
var events = [ 
 
    { name: 'band1', type: 'concert', subtype: 'rock' }, 
 
    { name: 'band2', type: 'concert', subtype: 'jazz' }, 
 
    { name: 'band3', type: 'concert', subtype: 'jazz' }, 
 
    { name: 'fun1', type: 'festival', subtype: 'beer' }, 
 
    { name: 'fun2', type: 'festival', subtype: 'food' }, 
 
]; 
 

 
var res = organize(events, ['type','subtype']); 
 

 
console.log(res);

+0

很好地完成!今晚我没有时间查看它,但是将您的功能复制并粘贴到我的代码中就像魅力一样!更干净。我很高兴能在以后再回过头来看看。我有一个预感减少将是有用的,但我总是忽视它赞成地图和过滤器。谢谢! – MattyRad

+0

不客气;-) – trincot

0

你可以使用_.groupBy()LoDash库:

var source = [ 
 
    { name: 'band1', type: 'concert', subtype: 'rock' }, 
 
    { name: 'band2', type: 'concert', subtype: 'jazz' }, 
 
    { name: 'band3', type: 'concert', subtype: 'jazz' }, 
 
    { name: 'fun1', type: 'festival', subtype: 'beer' }, 
 
    { name: 'fun2', type: 'festival', subtype: 'food' }, 
 
]; 
 
    
 
var groupedByType = _.groupBy(source, 'type'); 
 
console.log(groupedByType); 
 
    
 
var groupedByTypeAndSubtype = {}; 
 
for (var i in groupedByType) { 
 
    groupedByTypeAndSubtype[i] = _.groupBy(groupedByType[i], 'subtype'); 
 
} 
 

 
console.log(groupedByTypeAndSubtype);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.16.2/lodash.js"></script>