utilizzando lodash .groupBy. come aggiungere le proprie chiavi per l'output raggruppato?


104

Ho questi dati di esempio restituiti da un'API.

Sto usando Lodash's _.groupByper convertire i dati in un oggetto che posso usare meglio. I dati grezzi restituiti sono questi:

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

Voglio che la _.groupByfunzione restituisca un oggetto simile a questo:

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

Attualmente sto usando

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

che sta restituendo questo.

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

i raggruppamenti sono corretti, ma mi piacerebbe davvero aggiungere le chiavi che voglio ( color, users). è possibile utilizzare _.groupBy? o qualche altra LoDashutilità?

Risposte:


140

Puoi farlo in 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>


Risposta originale

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

Demo in linea

Nota: Lodash 4.0 in poi, la .pairsfunzione è stata rinominata_.toPairs()


Molto elegante, ma difficile da capire. Puoi spiegare i passaggi intermedi, in particolare l'associazione e la chiusura lampo (e la doppia zip, poiché _.objectè un alias per _.zipObject).
Benny Bottema

3
lodash 3.10.0 e alcuni log per ogni passaggio: jsfiddle.net/plantface/WYCF8/171 . È ancora un puzzle, ma ci sto arrivando. Non ho ancora usato _.zipe _.paircosì tanto.
Benny Bottema

12
In lodash 4.x, il pairs()metodo non esiste più. Una versione aggiornata di lodash 4.0 di questo esempio è:.chain(data).groupBy('color') .toPairs().map(function (pair) { return _.zipObject(['Name', 'Suppliers'], air); }).value();
Erik Schierboom

5
Sento che loadash dovrebbe avere una funzione che fa questa cosa molto esatta. Penso che gli utenti desiderino raggruppare sempre una serie di oggetti in base a una proprietà.
Adam Klein

1
L'utilizzo _.chainè considerato una cattiva pratica ora.
Pawel

89

Non è così semplice?

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

4
Questo mi sembra molto più pulito e sembra restituire gli stessi risultati. Grazie!
Jeremy A. West

3
Wow. che sintassi è questa? La prima volta che vedi che puoi passare l'array al costruttore
Wei-jye

Questa dovrebbe essere la risposta accettata. Semplice e pulito.
Tiago Stapenhorst Martins

17

un altro modo

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

Simile alla risposta di @ thefourtheye ma un po 'più facile da capire
Martin Magakian,

Sei il mio eroe
AlkanV

17

La risposta con il voto più alto utilizza la funzione Lodash _.chainche ora è considerata una cattiva pratica "Perché usare _.chainè un errore".

Ecco alcune righe che affrontano il problema dal punto di vista della programmazione funzionale :

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)

Dove si inputtrova un array che vuoi convertire.


Ho provato a usare flow()invece di chain()qui, ma il controllo del tipo di dattiloscritto semplicemente impazzisce con le funzioni composte. Spero che abbiamo lo stesso livello di supporto che abbiamo attualmente in RxJS pipe(), ad esempio in lodash.
BrunoJCM

Mi piace molto la tua sintassi map (), molto interessante map((users, color) => ({color, users}))invece dimap((value, key) => ({ color: key, users: value }))
Gil Epshtain

7

Grazie @thefourtheye , il tuo codice è stato di grande aiuto. Ho creato una funzione generica dalla tua soluzione utilizzando la versione 4.5.0 di Lodash.

function groupBy(dataToGroupOn, fieldNameToGroupOn, fieldNameForGroupName, fieldNameForChildren) {
            var result = _.chain(dataToGroupOn)
             .groupBy(fieldNameToGroupOn)
             .toPairs()
             .map(function (currentItem) {
                 return _.zipObject([fieldNameForGroupName, fieldNameForChildren], currentItem);
             })
             .value();
            return result;
        }

Per usarlo:

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

Ecco il violinista aggiornato;

https://jsfiddle.net/sc2L9dby/


5

Ecco una versione aggiornata utilizzando lodash 4 ed ES6

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

2

Suggerirei un approccio diverso, usando la mia libreria potresti farlo in poche righe:

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

var result = groupMe(collection);

Questo sarebbe un po 'difficile con lodash o underscore perché gli argomenti sono nell'ordine opposto, quindi dovresti usare _.partialmolto.


2

Esempio groupBy e somma di una colonna utilizzando 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);

bello ... e aggiornato
Peter van der Lely

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.