javascript 使用 Lodash 或 Underscore 按多列对对象进行分组
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/29587488/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Grouping objects by multiple columns with Lodash or Underscore
提问by codebased
I have following object records
:
我有以下对象records
:
{
"notes":[
{
"id":1,
"description":"hey",
"userId":2,
"replyToId":null,
"postId":2,
"parentId":null
},
{
"id":5,
"description":"hey test",
"userId":3,
"replyToId":null,
"postId":2,
"parentId":null
},
{
"id":2,
"description":"how are you",
"userId":null,
"replyToId":2,
"postId":2,
"parentId":null,
"user":null
}
]
}
I want to output it as:
我想将其输出为:
2
object with id 1
object with id 2 (because replyToId value is same as userId
3
object with id 5
So basically I want to consider UserId and replyToId value under the same group.
所以基本上我想考虑同一组下的 UserId 和 replyToId 值。
I have build my own mixin under lodash, wrapping groupBy method as:
我在 lodash 下构建了自己的 mixin,将 groupBy 方法包装为:
mixin({
splitGroupBy: function(list, groupByIter){
if (_.isArray(groupByIter)) {
function groupBy(obj) {
return _.forEach(groupByIter, function (key){
if ( !!obj[key] ) return obj[key]
});
}
} else {
var groupBy = groupByIter;
}
debugger;
var groups = _.groupBy(list, groupBy);
return groups;
}
});
Call looks like this:
调用看起来像这样:
_.splitGroupBy(data.notes,['userId', 'replyToId']);
The output is coming without group. Even when I have tried with _.map
instead _.forEach
the split is not happening correctly.
输出是没有组的。甚至当我试图用_.map
,而不是_.forEach
分裂没有正确发生。
回答by Gruff Bunny
A solution using underscore:
使用下划线的解决方案:
var props = ['userId', 'replyToId'];
var notNull = _.negate(_.isNull);
var groups = _.groupBy(record.notes, function(note){
return _.find(_.pick(note, props), notNull);
});
回答by robertklep
This can probably done much prettier, but it should work:
这可能会做得更漂亮,但它应该有效:
lodash.mixin({
splitGroupBy: function(list, groupByIter) {
var _ = this, groupBy;
if (lodash.isArray(groupByIter)) {
groupBy = function(obj) {
return _(obj) .pick(groupByIter)
.values()
.without(null, undefined)
.first();
};
} else {
groupBy = groupByIter;
}
var groups = _.groupBy(list, groupBy);
return groups;
}
});
回答by nikoshr
You could map your list of attributes to their respective values and pick the first non falsy value as your group key:
您可以将您的属性列表映射到它们各自的值,并选择第一个非虚假值作为您的组键:
_.mixin({
splitGroupBy: function(list, groupByIter){
if (!_.isArray(groupByIter))
return _.groupBy(list, groupByIter);
return _.groupBy(list, function(o) {
var values = _.map(groupByIter, function(k) {
return o[k];
});
return _.find(values);
});
}
});
var data = {
"notes":[
{
"id":1,
"userId":2,
"replyToId":null
},
{
"id":5,
"userId":3,
"replyToId":null
},
{
"id":2,
"userId":null,
"replyToId":2
}
]
};
_.mixin({
splitGroupBy: function(list, groupByIter){
if (!_.isArray(groupByIter))
return _.groupBy(list, groupByIter);
return _.groupBy(list, function(o) {
var values = _.map(groupByIter, function(k) {
return o[k];
});
return _.find(values);
});
}
});
snippet.log(JSON.stringify(_.splitGroupBy(data.notes,['userId', 'replyToId'])));
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<!-- Provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
回答by Retsam
Assuming userId
and replyToId
are mutually exclusive (i.e. you either have a userId
or a replyToId
, but never both) as they are in the sample data, then specifying a custom grouping function works:
假设userId
和replyToId
是互斥的(即您有 auserId
或 a replyToId
,但从来没有两者),因为它们在示例数据中,然后指定自定义分组函数有效:
_.groupBy(data.notes, function(note) {
return note.userId || note.replyToId;
});
回答by YairTawil
You can use stringify object as key.
您可以使用 stringify 对象作为键。
_.groupBy(notes, ({ userId, replyToId }) => JSON.stringify({ userId, replyToId }));
output:
输出:
{
"{\"userId\":2,\"replyToId\":null}": [
{
"id": 1,
"description": "hey",
"userId": 2,
"replyToId": null,
"postId": 2,
"parentId": null
}
],
"{\"userId\":3,\"replyToId\":null}": [
{
"id": 5,
"description": "hey test",
"userId": 3,
"replyToId": null,
"postId": 2,
"parentId": null
}
],
"{\"userId\":null,\"replyToId\":2}": [
{
"id": 2,
"description": "how are you",
"userId": null,
"replyToId": 2,
"postId": 2,
"parentId": null,
"user": null
}
]
}