Grouping objects by multiple columns with Lodash or Underscore

一曲冷凌霜 提交于 2019-12-05 03:55:32

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);
    });

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;
  }
});

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>

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:

_.groupBy(data.notes, function(note) {
    return note.userId || note.replyToId;
});
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!