如何使用下划线.groupBy函数根据多个属性对json对象数组进行分组?

时间:2015-07-06 10:04:26

标签: javascript arrays underscore.js lodash

我有一个json对象数组,我希望groupBy()基于多个属性,即

我有:

[
  {
     prop1:val1,
     prop2:val2,
     prop3:val3,
     prop4:val4
  }
]

现在如果我只想按prop1分组,我想我可以做到:

_.groupBy(givenArray, 'prop1');

如果我必须按prop1prop2prop3分组,即(prop1 && prop2 && prop3)

,我该怎么办?

请指导。

2 个答案:

答案 0 :(得分:1)

您可以将目标值设置为array,然后将其格式化为string,或者只是将它们转换为字符串形式并合并:

_.groupBy(givenArray, function(item) {
   var keys = _.pick(item, 'prop1', 'prop2', 'prop3');
   // If all are string or number,
   // return keys.join('_@%@_'); // this prevent ['ab', 'a'] generate same key to ['a', 'ba'];
   return JSON.stringify(keys);
});

JSON.stringify也许是创建组合密钥的众多方法之一,我不确定您的vals是什么(字符串,数字或其他),所以我只是在这里使用stringify。

答案 1 :(得分:1)

这实际上取决于你想要的最终结构。

如果你不介意非平面对象结构,你可以进行嵌套的_.groupBy调用:

var result = _(givenArray) //begin chain
.groupBy('a')
.mapValues(function(groupedByA) {
     return _(groupedByA) //begin chain
    .groupBy('b')
    .mapValues(function (groupedByAAndB) {
        return _.groupBy(groupedByAAndB, 'c');
    })
    .value(); //end chain
})
.value(); //end chain
//Then you can do things like:
result[5][4][3]; //All items where a=5, b=4, and c=3.

这里的缺点是,您所分组的每个属性都有额外的嵌套级别,如果没有result[5][4]的任何结果,a=5将会爆炸。 (虽然您可以使用像koalaesce这样的库)

或者,如果你想要一个扁平的物体结构,但不要介意它有点笨拙地访问这些物品,那么:

var result = _.groupBy(givenArray, function (item) {
    return JSON.stringify(_.pick(item, 'a','b','c'));
});

//Much simpler above, but accessed like: 
result[JSON.stringify({a: 5, b:4, c:3})]

更简单,并且可以通过更多的事情进行分组更好...但是使用起来很尴尬,因为密钥是完整的JSON字符串;但是你也没有第一个选项的null问题。

您也可以使用_.values或等效项将平面对象结构转换为单个数组数组。然后显然没有"随机"访问获取具有给定值a,b和c的所有项目,但您始终可以循环遍历它。