使用lodash .groupBy。如何为分组输出添加自己的密钥?


104

我有从API返回的样本数据。

我正在使用Lodash _.groupBy将数据转换成可以更好使用的对象。返回的原始数据是这样的:

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

我希望_.groupBy函数返回一个看起来像这样的对象:

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

目前我正在使用

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

这正在返回。

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

分组是正确的,但是我真的很想添加我想要的键(colorusers)。这可能使用_.groupBy吗?或其他LoDash实用程序?

Answers:


140

您可以在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>


原始答案

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

在线演示

注意:从 Lodash 4.0开始,该.pairs功能已重命名为_.toPairs()


很漂亮,但是很难缠住我的头。您能否解释一下两者之间的步骤,尤其是配对和压缩(以及双压缩,因为_.object是的别名_.zipObject)。
Benny Bottema,2015年

3
lodash 3.10.0以及每个步骤的一些日志记录:jsfiddle.net/plantface/WYCF8/171。这仍然是一个难题,但我要到达那里。还没用过_.zip_.pair还很多。
Benny Bottema

12
在lodash 4.x中,该pairs()方法不再存在。此示例的最新lodash 4.0版本为:.chain(data).groupBy('color') .toPairs().map(function (pair) { return _.zipObject(['Name', 'Suppliers'], air); }).value();
Erik Schierboom

5
我觉得loadash应该具有执行此功能的功能。我认为用户会一直希望按属性对对象数组进行分组。
亚当·克莱因

1
_.chain现在认为使用是不好的做法。
Pawel

88

这不是很简单吗?

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

4
对我来说,这似乎更干净,并且似乎返回了相同的结果。谢谢!
杰里米·A·西

3
哇。这是什么语法?第一次看到你可以将数组传递到构造
伟捷

这应该是公认的答案。简单干净。
Tiago Stapenhorst Martins,


17

投票率最高的答案使用Lodash _.chain函数,现在 “为什么使用是错误的” 被认为是不好的做法_.chain

这是从函数式编程的角度解决问题的一些方法:

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)

input您要转换的数组在哪里。


我尝试使用flow()而不是chain()这里,但是Typescript的类型检查只是对组合函数发疯了。我希望我们能获得与RxJS相同的支持水平pipe(),例如lodash。
BrunoJCM

我真的很喜欢您的map()语法,非常酷,map((users, color) => ({color, users}))而不是map((value, key) => ({ color: key, users: value }))
Gil Epshtain

7

感谢@thefourtheye,您的代码提供了很大帮助。我使用Lodash的4.5.0版本从您的解决方案中创建了一个泛型函数。

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

要使用它:

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

这是更新的提琴手;

https://jsfiddle.net/sc2L9dby/


5

这是使用lodash 4和ES6的更新版本

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

2

我建议使用另一种方法,使用我自己的库,您可以在几行中完成此操作:

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

var result = groupMe(collection);

使用lodash或Underscore会有点困难,因为参数的顺序相反,因此您必须使用_.partial很多。


2

使用Lodash 4.17.4的示例groupBy和列总和

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

很好...并且是最新的
Peter van der Lely

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.