使用lodash . groupby.如何为分组输出添加自己的键

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

本文关键字:输出 添加 自己的 lodash groupby 使用      更新时间:2023-09-26

我从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: [{...}]}

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

您可以在下划线和Lodash(3)中这样做。X和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()

这不是很简单吗?

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

最高投票的答案使用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是要转换的数组

另一种方式

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

谢谢@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');

这是更新后的fiddler;

https://jsfiddle.net/sc2L9dby/

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

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

  • 使用reduce聚合数据
  • 如果acc[color]为null (null or undefined),则使用logical nullish assignment

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

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

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

示例使用Lodash 4.17.4查询一个列的groupBy和sum

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

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

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

对于lodash或下划线来说,这有点困难,因为参数的顺序相反,所以您必须经常使用_.partial

  const groupBy = (array, key, name) => {
    return array.reduce((result, obj) => {
      result[obj[key]] = result[obj[key]] || {
        location: obj[name],
        child: [],
      };
      // result[obj[key]] ??= {
      //   location: obj[name],
      //   child: []
      // };
      result[obj[key]].child.push(obj);
      return result;
    }, {});
  };
  const items = [
    {
      id: 1,
      age: 75,
      name: 'Kumar',
      location: 'chennai',
    },
    {
      id: 1,
      age: 25,
      name: 'Christo',
      location: 'Dindigul',
    },
    {
      id: 1,
      age: 28,
      name: 'SK',
      location: 'chennai',
    },
    {
      id: 1,
      age: 21,
      name: 'Ram',
      location: 'chennai',
    },
    {
      id: 1,
      age: 21,
      name: 'ravi',
      location: 'chennai',
    },
  ];
  let obj = groupBy(items, 'age', 'location');
  const result = Object.keys(obj).map((key) => [obj[key]][0]);
  console.log(result);
 

2017年这样做

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