menggunakan lodash .groupBy. bagaimana cara menambahkan kunci Anda sendiri untuk keluaran yang dikelompokkan?


104

Saya memiliki data sampel ini yang dikembalikan dari API.

Saya menggunakan Lodash _.groupByuntuk mengubah data menjadi objek yang dapat saya gunakan dengan lebih baik. Data mentah yang dikembalikan adalah ini:

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

Saya ingin _.groupByfungsi mengembalikan objek yang terlihat seperti ini:

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

Saat ini saya menggunakan

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

yang mengembalikan ini.

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

pengelompokannya benar, tetapi saya benar-benar ingin menambahkan kunci yang saya inginkan ( color, users). apakah ini mungkin digunakan _.groupBy? atau LoDashutilitas lain ?

Jawaban:


140

Anda dapat melakukannya seperti ini di 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>


Jawaban Asli

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

Demo Online

Catatan: Lodash 4.0 dan seterusnya, .pairsfungsi telah diubah namanya menjadi_.toPairs()


Sangat bagus, tapi sulit untuk membungkus kepalaku. Bisakah Anda menjelaskan langkah-langkah di antaranya, terutama pemasangan dan pembuatan zip (dan zip ganda, karena _.objectmerupakan alias untuk _.zipObject).
Benny Bottema

3
lodash 3.10.0 dan beberapa pencatatan untuk setiap langkah: jsfiddle.net/plantface/WYCF8/171 . Ini masih teka-teki, tapi saya akan kesana. Belum pernah digunakan _.zipdan _.pairmasih banyak lagi.
Benny Bottema

12
Di lodash 4.x, pairs()metode tersebut tidak ada lagi. Versi lodash 4.0 yang diperbarui dari contoh ini adalah:.chain(data).groupBy('color') .toPairs().map(function (pair) { return _.zipObject(['Name', 'Suppliers'], air); }).value();
Erik Schierboom

5
Saya merasa seperti loadash harus memiliki fungsi yang melakukan hal ini dengan tepat. Saya akan berpikir pengguna ingin mengelompokkan array objek berdasarkan properti setiap saat.
Adam Klein

1
Menggunakan _.chaindianggap sebagai praktik yang buruk sekarang.
Pawel

90

Bukankah sesederhana ini?

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

4
Ini tampak jauh lebih bersih bagi saya, dan tampaknya mengembalikan hasil yang sama. Terima kasih!
Jeremy A. West

3
Wow. sintaks apa ini? Pertama kali melihat bahwa Anda dapat meneruskan larik ke konstruktor
Wei-jye

Ini harus menjadi jawaban yang diterima. Sederhana dan bersih.
Tiago Stapenhorst Martins

17

cara lain

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

Mirip dengan jawaban @ thefourtheye tetapi sedikit lebih mudah dipahami
Martin Magakian

Anda adalah pahlawan saya
AlkanV

17

Jawaban dengan suara terbanyak menggunakan fungsi Lodash _.chainyang sekarang dianggap sebagai praktik buruk "Mengapa menggunakan _.chainadalah kesalahan."

Berikut adalah beberapa baris yang mendekati masalah dari perspektif pemrograman fungsional :

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)

Di mana inputarray yang ingin Anda konversi.


Saya mencoba menggunakan flow()alih-alih di chain()sini, tetapi pemeriksaan jenis skrip menjadi gila dengan fungsi yang disusun. Saya berharap kami memiliki tingkat dukungan yang sama seperti yang kami miliki saat ini di RxJS pipe(), misalnya, di lodash.
BrunoJCM

Saya sangat suka sintaks peta () Anda, sangat keren map((users, color) => ({color, users}))daripadamap((value, key) => ({ color: key, users: value }))
Gil Epshtain

7

Terima kasih @thefourtheye , kode Anda sangat membantu. Saya membuat fungsi umum dari solusi Anda menggunakan Lodash versi 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;
        }

Untuk menggunakannya:

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

Berikut adalah fiddler yang diperbarui;

https://jsfiddle.net/sc2L9dby/


5

Ini adalah versi terbaru menggunakan lodash 4 dan ES6

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

2

Saya akan menyarankan pendekatan yang berbeda, dengan menggunakan perpustakaan saya sendiri, Anda dapat melakukan ini dalam beberapa baris:

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

var result = groupMe(collection);

Ini akan sedikit sulit dengan lodash atau Underscore karena argumen berada dalam urutan yang berlawanan, jadi Anda harus menggunakan _.partialbanyak.


2

Contoh groupBy dan jumlah kolom menggunakan 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);

bagus ... dan terkini
Peter van der Lely

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.