using lodash .groupBy. how to add your own keys for grouped output?

余生长醉 提交于 2019-11-26 08:45:03

问题


I have this sample data returned from an API.

I\'m using Lodash\'s _.groupBy to convert the data into an object I can use better. The raw data returned is this:

[
    {
        \"name\": \"jim\",
        \"color\": \"blue\",
        \"age\": \"22\"
    },
    {
        \"name\": \"Sam\",
        \"color\": \"blue\",
        \"age\": \"33\"
    },
    {
        \"name\": \"eddie\",
        \"color\": \"green\",
        \"age\": \"77\"
    }
]

I want the _.groupBy function to return an object that looks like this:

[
    {
        color: \"blue\",
        users: [
            {
                \"name\": \"jim\",
                \"color\": \"blue\",
                \"age\": \"22\"
            },
            {
                \"name\": \"Sam\",
                \"color\": \"blue\",
                \"age\": \"33\"
            }
        ]
    },
    {
        color: \"green\",
        users: [
            {
                \"name\": \"eddie\",
                \"color\": \"green\",
                \"age\": \"77\"
            }
        ]
    }
]

Currently I\'m using

_.groupBy(a, function(b) { return b.color})

which is returning this.

{blue: [{..}], green: [{...}]}

the groupings are correct, but I\'d really like to add the keys I want (color, users). is this possible using _.groupBy? or some other LoDash utility?


回答1:


You can do it like this in Lodash 4.x

var data = [{
  "name": "jim",
  "color": "blue",
  "age": "22"
}, {
  "name": "Sam",
  "color": "blue",
  "age": "33"
}, {
  "name": "eddie",
  "color": "green",
  "age": "77"
}];

console.log(
  _.chain(data)
    // Group the elements of Array based on `color` property
    .groupBy("color")
    // `key` is group's name (color), `value` is the array of objects
    .map((value, key) => ({ color: key, users: value }))
    .value()
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>

Original Answer

var result = _.chain(data)
    .groupBy("color")
    .pairs()
    .map(function(currentItem) {
        return _.object(_.zip(["color", "users"], currentItem));
    })
    .value();
console.log(result);

Online Demo

Note: Lodash 4.0 onwards, the .pairs function has been renamed to _.toPairs()




回答2:


Isn't it this simple?

var result = _(data)
            .groupBy(x => x.color)
            .map((value, key) => ({color: key, users: value}))
            .value();



回答3:


another way

_.chain(data)
    .groupBy('color')
    .map((users, color) => ({ users, color }))
    .value();



回答4:


Highest voted answer uses Lodash _.chain function which is considered a bad practice now "Why using _.chain is a mistake."

Here is a fewliner that approaches the problem from functional programming perspective:

import tap from "lodash/fp/tap";
import flow from "lodash/fp/flow";
import groupBy from "lodash/fp/groupBy";

const map = require('lodash/fp/map').convert({ 'cap': false });

const result = flow(
      groupBy('color'),
      map((users, color) => ({color, users})),
      tap(console.log)
    )(input)

Where input is an array that you want to convert.




回答5:


Thanks @thefourtheye, your code greatly helped. I created a generic function from your solution using the version 4.5.0 of Lodash.

function groupBy(dataToGroupOn, fieldNameToGroupOn, fieldNameForGroupName, fieldNameForChildren) {
            var result = _.chain(dataToGroupOn)
             .groupBy(fieldNameToGroupOn)
             .toPairs()
             .map(function (currentItem) {
                 return _.zipObject([fieldNameForGroupName, fieldNameForChildren], currentItem);
             })
             .value();
            return result;
        }

To use it:

var result = groupBy(data, 'color', 'colorId', 'users');

Here is the updated fiddler;

https://jsfiddle.net/sc2L9dby/




回答6:


Here is an updated version using lodash 4 and ES6

const result = _.chain(data)
    .groupBy("color")
    .toPairs()
    .map(pair => _.zipObject(['color', 'users'], pair))
    .value();



回答7:


I would suggest a different approach, using my own library you could do this in a few lines:

var groupMe = sequence(
  groupBy(pluck('color')),
  forOwn(function(acc, k, v) {
    acc.push({colors: k, users: v});
    return acc;
  },[])
);

var result = groupMe(collection);

This would a be a bit difficult with lodash or Underscore because the arguments are in the opposite order order, so you'd have to use _.partial a lot.




回答8:


Example groupBy and sum of a column using Lodash 4.17.4

   var data = [{
                "name": "jim",
                "color": "blue",
                "amount": 22
                }, {
                "name": "Sam",
                "color": "blue",
                "amount": 33
                }, {
               "name": "eddie",
               "color": "green",
               "amount": 77
              }];

      var result = _(data)
                   .groupBy(x => x.color)
                   .map((value, key) => 
                   ({color: key,
                    totalamount: _.sumBy(value,'amount'),
                    users: value})).value();

                    console.log(result);



回答9:


In 2017 do so

_.chain(data)
  .groupBy("color")
  .toPairs()
  .map(item => _.zipObject(["color", "users"], item))
  .value();


来源:https://stackoverflow.com/questions/23600897/using-lodash-groupby-how-to-add-your-own-keys-for-grouped-output

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!