2016-11-23 30 views
21

Czy ktoś wie o (również jeśli jest to możliwe), aby zgrupować tablicę obiektów za pomocą klucza obiektu, a następnie utworzyć nową tablicę obiektów na podstawie grupowania? Na przykład, mam tablicę obiektów samochodem:Jak pogrupować tablicę obiektów według klucza

var cars = [ 
    { 
     'make': 'audi', 
     'model': 'r8', 
     'year': '2012' 
    }, { 
     'make': 'audi', 
     'model': 'rs5', 
     'year': '2013' 
    }, { 
     'make': 'ford', 
     'model': 'mustang', 
     'year': '2012' 
    }, { 
     'make': 'ford', 
     'model': 'fusion', 
     'year': '2015' 
    }, { 
     'make': 'kia', 
     'model': 'optima', 
     'year': '2012' 
    }, 
]; 

chcę zrobić nową tablicę obiektów samochód jest zgrupowane według make:

var cars = { 
    'audi': [ 
     { 
      'model': 'r8', 
      'year': '2012' 
     }, { 
      'model': 'rs5', 
      'year': '2013' 
     }, 
    ], 

    'ford': [ 
     { 
      'model': 'mustang', 
      'year': '2012' 
     }, { 
      'model': 'fusion', 
      'year': '2015' 
     } 
    ], 

    'kia': [ 
     { 
      'model': 'optima', 
      'year': '2012' 
     } 
    ] 
} 
+0

Czy patrzysz na 'groupBy'? – SLaks

+1

Twój wynik jest nieprawidłowy. –

Odpowiedz

12

Timo's answer to w jaki sposób to zrobić. Prosty _.groupBy i pozwala na pewne duplikacje obiektów w zgrupowanej strukturze.

Jednak OP również poprosił o usunięcie duplikatów make kluczy. Jeśli chcesz przejść całą drogę:

var grouped = _.mapValues(_.groupBy(cars, 'make'), 
          clist => clist.map(car => _.omit(car, 'make'))); 

console.log(grouped); 

Wynik:

{ audi: 
    [ { model: 'r8', year: '2012' }, 
    { model: 'rs5', year: '2013' } ], 
    ford: 
    [ { model: 'mustang', year: '2012' }, 
    { model: 'fusion', year: '2015' } ], 
    kia: [ { model: 'optima', year: '2012' } ] } 

Jeśli chciał to zrobić za pomocą underscore.js pamiętać, że jego wersja _.mapValues nazywa _.mapObject.

21

Szukasz _.groupBy().

Usuwanie właściwość jesteś grupowania przez z obiektów powinien być trywialne, jeśli wymagane:

var cars = [{'make':'audi','model':'r8','year':'2012'},{'make':'audi','model':'rs5','year':'2013'},{'make':'ford','model':'mustang','year':'2012'},{'make':'ford','model':'fusion','year':'2015'},{'make':'kia','model':'optima','year':'2012'},]; 
 

 
var grouped = _.groupBy(cars, function(car) { 
 
    return car.make; 
 
}); 
 

 
console.log(grouped);
<script src='https://cdn.jsdelivr.net/lodash/4.17.2/lodash.min.js'></script>


Jako bonus, można uzyskać nawet ładniejszy składni z ES6 funkcji strzałek :

const grouped = _.groupBy(cars, car => car.make); 
+5

A jeśli chcesz go jeszcze krócej, 'var grouped = _.groupBy (cars, 'make');' Nie ma potrzeby korzystania z funkcji, jeśli accessor jest prostą nazwą właściwości. –

+0

doskonały, dziękuję! –

+0

To jest geniusz! – Daria

51

W zwykłym JavaScript, można użyć Array#reduce z obiektem

var cars = [{ make: 'audi', model: 'r8', year: '2012' }, { make: 'audi', model: 'rs5', year: '2013' }, { make: 'ford', model: 'mustang', year: '2012' }, { make: 'ford', model: 'fusion', year: '2015' }, { make: 'kia', model: 'optima', year: '2012' }], 
 
    result = cars.reduce(function (r, a) { 
 
     r[a.make] = r[a.make] || []; 
 
     r[a.make].push(a); 
 
     return r; 
 
    }, Object.create(null)); 
 

 
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

2

Możesz spróbować zmodyfikować obiekt wewnątrz funkcji o nazwie per iteration przez _.groupBy func. Zauważ, że tablica źródłowa zmienia swoje elementy!

var res = _.groupBy(cars,(car)=>{ 
    const makeValue=car.make; 
    delete car.make; 
    return makeValue; 
}) 
console.log(res); 
console.log(cars); 
+1

Podczas gdy ten kod może rozwiązać pytanie, [w tym wyjaśnienie] (http://meta.stackexchange.com/questions/114762/explaining-entirely-code- oparte-odpowiedzi) o tym, jak i dlaczego to rozwiązuje problem, mogłoby naprawdę przyczynić się do poprawy jakości twojego wpisu. Pamiętaj, że odpowiadasz na pytanie dla czytelników w przyszłości, a nie tylko pytasz teraz! Zmodyfikuj swoją odpowiedź, aby dodać wyjaśnienie i podaj, jakie ograniczenia i założenia mają zastosowanie. – Makyen

+0

OK, dziękuję za sugestie! – nickxbs

1

Wersja krótka w ES5:

result = cars.reduce((h, a) => ({ 
    ...h, 
    [a.make]: (h[a.make] || []).push(a) 
}), {}) 
0

Oto swój własny groupBy funkcja, która jest uogólnieniem kodu z: https://github.com/you-dont-need/You-Dont-Need-Lodash-Underscore

function groupBy(xs, f) { 
 
    return xs.reduce((r, v, i, a, k = f(v)) => ((r[k] || (r[k] = [])).push(v), r), {}); 
 
} 
 

 
const cars = [{ make: 'audi', model: 'r8', year: '2012' }, { make: 'audi', model: 'rs5', year: '2013' }, { make: 'ford', model: 'mustang', year: '2012' }, { make: 'ford', model: 'fusion', year: '2015' }, { make: 'kia', model: 'optima', year: '2012' }]; 
 

 
const result = groupBy(cars, (c) => c.make); 
 
console.log(result);