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.