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

时间:2014-05-12 04:06:37

标签: javascript sorting underscore.js grouping lodash

我从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实用程序?

10 个答案:

答案 0 :(得分:97)

你可以这样做

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

Online Demo

注意: Lodash 4.0以后,.pairs功能已重命名为_.toPairs()

答案 1 :(得分:63)

难道不是这么简单吗?

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

答案 2 :(得分:13)

另一种方式

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

答案 3 :(得分:9)

最高投票回答使用 Lodash _.chain函数,现在被视为不良做法 "Why using _.chain is a mistake."

以下是从函数式编程角度解决问题的几个方法:

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是您要转换的数组。

答案 4 :(得分: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 :(得分:5)

这是使用lodash 4和ES6

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

答案 6 :(得分:2)

我建议采用不同的方法,使用my own library你可以用几行来做到这一点:

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

答案 7 :(得分:2)

使用 lodash 的其他答案看起来不错。

我建议使用 JavaScript 的不同方法,例如 Array#reduceobject for storing??= 语法。因此,它只需要 O(n) 的时间复杂度。

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

const result = data.reduce((acc, {name, color, age}) => {
 acc[color] ??= {color: color, users: []};
 acc[color].users.push({name, color, age});
 
 return acc;
}, {});
console.log(Object.values(result));

答案 8 :(得分:0)

示例groupBy和使用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 :(得分:-2)

2017年这样做

val = next(dropwhile(lambda x: x[0]==x[1], zip(coordinates, ocoords[0])))
print(val[0])  
# [(5, 2), (6, 2)]