lodash .groupBy kullanarak. gruplanmış çıktı için kendi anahtarlarınızı nasıl ekleyebilirsiniz?


106

Bu örnek verileri bir API'den döndürdüm.

_.groupByVerileri daha iyi kullanabileceğim bir nesneye dönüştürmek için Lodash kullanıyorum . Döndürülen ham veriler şudur:

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

İstediğim _.groupBybakışlar böyle olduğu fonksiyon bir nesneyi döndürmek için:

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

Şu anda kullanıyorum

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

bu da geri dönüyor.

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

gruplamalar doğru, ancak gerçekten istediğim anahtarları ( color, users) eklemek istiyorum . bu mümkün _.groupBymü? veya başka bir LoDashyardımcı program?

Yanıtlar:


145

Lodash 4.x'de bunu yapabilirsiniz.

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>


Orijinal Cevap

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

Çevrimiçi Demo

Not: Lodash 4.0'dan itibaren .pairsişlev şu şekilde yeniden adlandırılmıştır:_.toPairs()


Çok şık, ama kafamı dolaştırmak zor. Aradaki adımları, özellikle eşleştirme ve sıkıştırmayı (ve çift fermuar, çünkü _.objectbunun takma adıdır _.zipObject) açıklayabilir misiniz?
Benny Bottema

3
lodash 3.10.0 ve her adım için biraz günlük kaydı: jsfiddle.net/plantface/WYCF8/171 . Hala bir bulmaca, ama oraya gidiyorum. Henüz kullanılmadım _.zipve _.pairçok fazla.
Benny Bottema

12
Lodash 4.x'te pairs()yöntem artık mevcut değil. Bu örneğin güncellenmiş bir lodash 4.0 sürümü:.chain(data).groupBy('color') .toPairs().map(function (pair) { return _.zipObject(['Name', 'Suppliers'], air); }).value();
Erik Schierboom

5
Loadash'ın bunu tam olarak yapan bir işlevi olması gerektiğini düşünüyorum. Kullanıcıların her zaman bir özelliğe göre bir dizi nesneyi gruplamak isteyeceğini düşünürdüm.
Adam Klein

1
Kullanımı _.chainartık kötü bir uygulama olarak kabul edilmektedir.
Pawel

90

Bu kadar basit değil mi?

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

4
Bu bana çok daha temiz görünüyor ve aynı sonuçları veriyor gibi görünüyor. Teşekkürler!
Jeremy A. West

3
vay. bu hangi sözdizimi?
Diziyi kurucuya

Kabul edilen cevap bu olmalıdır. Basit ve temiz.
Tiago Stapenhorst Martins

17

diğer yol

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

@ Thefourtheye'ın cevabına benzer, ancak anlaşılması biraz daha kolay
Martin Magakian

Sen benim kahramanımsın
AlkanV

17

En yüksek oyu alan yanıt, artık kötü bir uygulama olarak kabul edilen Lodash _.chainişlevini kullanıyor "Neden_.chain bir hatadır".

Soruna işlevsel programlama perspektifinden yaklaşan bir kaç satır :

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)

inputDönüştürmek istediğiniz dizi nerede .


Burada kullanmak flow()yerine kullanmayı denedim chain(), ancak typcript'in tür denetimi, oluşturulmuş işlevlerle çılgınca gidiyor. Umarım şu anda RxJS'lerde pipe(), örneğin lodash'ta sahip olduğumuz destek düzeyine sahip oluruz.
BrunoJCM

Harita () sözdiziminizi gerçekten beğendim, map((users, color) => ({color, users}))yerine çok güzelmap((value, key) => ({ color: key, users: value }))
Gil Epshtain

7

Teşekkürler @thefourtheye , kodunuz çok yardımcı oldu. Lodash 4.5.0 sürümünü kullanarak çözümünüzden genel bir işlev oluşturdum.

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

Kullanmak için:

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

İşte güncellenmiş kemancı;

https://jsfiddle.net/sc2L9dby/


5

Lodash 4 ve ES6 kullanan güncellenmiş bir sürüm burada

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

2

Farklı bir yaklaşım öneririm, kendi kütüphanemi kullanarak bunu birkaç satırda yapabilirsiniz:

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

var result = groupMe(collection);

Bu, lodash veya Underscore ile biraz zor olurdu çünkü argümanlar ters sırada, bu yüzden _.partialçok kullanmalısın .


2

Örnek grup Lodash 4.17.4 kullanılarak bir sütunun toplamı ve toplamı

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

güzel ... ve güncel
Peter van der Lely

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.