2016-11-23 13 views
21

Có ai biết một cách (lodash nếu có thể) để nhóm một mảng đối tượng bằng một khóa đối tượng sau đó tạo một mảng đối tượng mới dựa trên nhóm không? Ví dụ, tôi có một mảng các đối tượng xe:Làm thế nào để nhóm một mảng các đối tượng theo khóa

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' 
    }, 
]; 

Tôi muốn thực hiện một mảng mới của các đối tượng xe đó là nhóm lại theo 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

Did bạn nhìn vào 'groupBy'? – SLaks

+1

kết quả của bạn không hợp lệ. –

Trả lời

12

Timo's answer là cách tôi sẽ làm điều đó. Đơn giản _.groupBy và cho phép một số trùng lặp trong các đối tượng trong cấu trúc được nhóm.

Tuy nhiên, OP cũng đã yêu cầu xóa các phím make trùng lặp. Nếu bạn muốn đi tất cả các cách:

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

console.log(grouped); 

Sản lượng:

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

Nếu bạn muốn làm điều này bằng Underscore.js, lưu ý rằng phiên bản của _.mapValues được gọi _.mapObject.

21

Bạn đang tìm kiếm _.groupBy().

Loại bỏ thuộc tính bạn đang nhóm phát từ các đối tượng phải là tầm thường nếu có yêu cầu:

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>


Như một phần thưởng, bạn sẽ có được cú pháp thậm chí đẹp hơn với các chức năng mũi tên ES6 :

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

Và nếu bạn muốn nó ngắn hơn, 'var grouped = _.groupBy (cars, 'make');' Không cần một hàm nào cả, nếu accessor là một tên thuộc tính đơn giản. –

+0

hoàn hảo, cảm ơn bạn! –

+0

Đây là thiên tài! – Daria

51

Trong đồng bằng Javascript, bạn có thể sử dụng Array#reduce với một đối tượng

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

Bạn có thể thử sửa đổi đối tượng bên trong hàm được gọi cho mỗi lần lặp bởi _.groupBy func. Lưu ý rằng mảng nguồn thay đổi các phần tử của anh ấy!

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

Mặc dù mã này có thể giải quyết được câu hỏi, [bao gồm giải thích] (http://meta.stackexchange.com/questions/114762/explaining-entirely-code- dựa trên câu trả lời) về cách thức và lý do giải quyết vấn đề này thực sự sẽ giúp cải thiện chất lượng bài đăng của bạn. Hãy nhớ rằng bạn đang trả lời câu hỏi cho độc giả trong tương lai, không chỉ là người hỏi ngay bây giờ! Vui lòng chỉnh sửa câu trả lời của bạn để thêm giải thích và đưa ra chỉ báo về những giới hạn và giả định được áp dụng. – Makyen

+0

Ok, cảm ơn đề xuất của bạn! – nickxbs

1

Phiên bản ngắn trong ES5:

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

Đây là groupBy chức năng rất riêng của bạn mà là một sự tổng quát của mã từ: 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);

Các vấn đề liên quan