次のオブジェクト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
}
]
}
私はそれを次のように出力したいと思います:
2
object with id 1
object with id 2 (because replyToId value is same as userId
3
object with id 5
したがって、基本的には、同じグループの下でUserIdとreplyToIdの値を検討したいと思います。
Lodashの下に独自のミックスインを作成し、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;
}
});
呼び出しは次のようになります。
_.splitGroupBy(data.notes,['userId', 'replyToId']);
出力はグループなしで来ています。代わりに_.map
を_.forEach
で試しても、分割が正しく行われていません。
アンダースコアを使用したソリューション:
var props = ['userId', 'replyToId'];
var notNull = _.negate(_.isNull);
var groups = _.groupBy(record.notes, function(note){
return _.find(_.pick(note, props), notNull);
});
属性のリストをそれぞれの値にマップし、最初の偽りのない値をグループキーとして選択できます。
_.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>
userId
とreplyToId
がサンプルデータにあるように相互に排他的であると仮定すると(つまり、userId
またはreplyToId
のいずれかがありますが、両方はありません)次に、カスタムグループ化関数を指定すると機能します。
_.groupBy(data.notes, function(note) {
return note.userId || note.replyToId;
});
これはおそらくもっときれいにできるでしょうが、うまくいくはずです:
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;
}
});