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 ?

pengguna1767105
sumber

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

thefourtheye
sumber
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();
Darragh
sumber
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();
stasovlas.dll
sumber
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.

Pawel
sumber
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/

Andrew
sumber
5

Ini adalah versi terbaru menggunakan lodash 4 dan ES6

const result = _.chain(data)
    .groupBy("color")
    .toPairs()
    .map(pair => _.zipObject(['color', 'users'], pair))
    .value();
matthew
sumber
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.

elclanrs
sumber
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);
Iyyappan Amirthalingam
sumber
bagus ... dan terkini
Peter van der Lely
-2

Pada 2017 lakukan itu

_.chain(data)
  .groupBy("color")
  .toPairs()
  .map(item => _.zipObject(["color", "users"], item))
  .value();
Владислав Сироштан
sumber