using lodash .groupBy. Wie füge ich meine eigenen Schlüssel für die gruppierte Ausgabe hinzu?


104

Ich habe diese Beispieldaten von einer API zurückgegeben.

Ich verwende Lodashs _.groupBy, um die Daten in ein Objekt zu konvertieren, das ich besser verwenden kann. Die zurückgegebenen Rohdaten lauten wie folgt:

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

Ich möchte, dass die _.groupByFunktion ein Objekt zurückgibt, das so aussieht:

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

Zur Zeit benutze ich

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

was dies zurückgibt.

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

Die Gruppierungen sind korrekt, aber ich möchte wirklich die gewünschten Schlüssel hinzufügen ( color, users). ist das möglich mit _.groupBy? oder ein anderes LoDashDienstprogramm?

Antworten:


140

Sie können dies in Lodash 4.x so tun

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>


Ursprüngliche Antwort

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

Online-Demo

Hinweis: Ab Lodash 4.0 wurde die .pairsFunktion in umbenannt_.toPairs()


Sehr geschickt, aber schwer, meinen Kopf herumzuwickeln. Können Sie die Schritte dazwischen erklären, insbesondere das Pairing und Zippen (und die doppelte Zip, da dies _.objectein Alias ​​für ist _.zipObject).
Benny Bottema

3
lodash 3.10.0 und einige Protokollierungen für jeden Schritt: jsfiddle.net/plantface/WYCF8/171 . Es ist immer noch ein Rätsel, aber ich komme dorthin. Noch nicht benutzt _.zipund _.pairso viel.
Benny Bottema

12
In lodash 4.x existiert die pairs()Methode nicht mehr. Eine aktualisierte lodash 4.0-Version dieses Beispiels ist:.chain(data).groupBy('color') .toPairs().map(function (pair) { return _.zipObject(['Name', 'Suppliers'], air); }).value();
Erik Schierboom

5
Ich denke, Loadash sollte eine Funktion haben, die genau das tut. Ich würde denken, dass Benutzer die ganze Zeit ein Array von Objekten nach einer Eigenschaft gruppieren möchten.
Adam Klein

1
Die Verwendung _.chainwird derzeit als schlechte Praxis angesehen.
Pawel

88

Ist es nicht so einfach?

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

4
Dies scheint mir viel sauberer zu sein und scheint die gleichen Ergebnisse zu liefern. Vielen Dank!
Jeremy A. West

3
Beeindruckend. Welche Syntax ist das? Zum ersten Mal sehen, dass Sie das Array an den Konstruktor übergeben können
Wei-jye

Dies sollte die akzeptierte Antwort sein. Einfach und sauber.
Tiago Stapenhorst Martins

17

ein anderer Weg

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

Ähnlich wie die Antwort von @ thefourtheye, aber etwas leichter zu verstehen
Martin Magakian

Du bist mein Held
AlkanV

17

Die Antwort mit der höchsten Bewertung_.chain verwendet die Lodash- Funktion, die derzeit als schlechte Praxis angesehen wird. "Warum ist die Verwendung ein Fehler ? "_.chain

Hier ist ein paar Zeilen, die sich dem Problem aus Sicht der funktionalen Programmierung nähern :

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)

Wo inputist ein Array, das Sie konvertieren möchten?


Ich habe versucht, flow()anstelle von chain()hier zu verwenden, aber die Typprüfung von Typoskript wird mit komponierten Funktionen einfach verrückt. Ich hoffe, wir haben die gleiche Unterstützung, die wir derzeit bei RxJS haben pipe(), zum Beispiel bei lodash.
BrunoJCM

Ich mag deine map () - Syntax sehr, sehr cool map((users, color) => ({color, users}))stattmap((value, key) => ({ color: key, users: value }))
Gil Epshtain

7

Vielen Dank an @thefourtheye , Ihr Code hat sehr geholfen. Ich habe aus Ihrer Lösung eine generische Funktion mit der Version 4.5.0 von Lodash erstellt.

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

Um es zu benutzen:

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

Hier ist der aktualisierte Geiger;

https://jsfiddle.net/sc2L9dby/


5

Hier ist eine aktualisierte Version mit lodash 4 und ES6

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

2

Ich würde einen anderen Ansatz vorschlagen. Wenn Sie meine eigene Bibliothek verwenden, können Sie dies in wenigen Zeilen tun:

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

var result = groupMe(collection);

Dies wäre bei lodash oder Underscore etwas schwierig, da die Argumente in der entgegengesetzten Reihenfolge angeordnet sind und Sie daher _.partialviel verwenden müssten .


2

Beispiel groupBy und Summe einer Spalte mit 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);

schön ... und auf dem neuesten Stand
Peter van der Lely

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.