web-dev-qa-db-ja.com

lodash .groupByを使用します。グループ化された出力用に独自のキーを追加する方法は?

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ユーティリティ?

76
user1767105

このようにできます

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() に名前が変更されました

103
thefourtheye

これは単純ではありませんか?

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

別の方法

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

最も投票数の多い回答は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は、変換する配列です。

10
Pawel

ありがとう@ 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/

7
andrew

これはlodash 4とES6を使用した更新バージョンです

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

自分のライブラリ を使用して別のアプローチをお勧めします。数行でこれを行うことができます。

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
elclanrs

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