Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

You can do it like this in both Underscore and Lodash (3.x and 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()


Isn't it this simple?

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

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.


another way

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

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/