有人知道一种方法(lodash如果可能的话)通过对象键分组对象数组,然后根据分组创建一个新的对象数组吗?例如,我有一个汽车对象数组:
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'
},
];
我想创建一个新的汽车对象数组,由make分组:
const cars = {
'audi': [
{
'model': 'r8',
'year': '2012'
}, {
'model': 'rs5',
'year': '2013'
},
],
'ford': [
{
'model': 'mustang',
'year': '2012'
}, {
'model': 'fusion',
'year': '2015'
}
],
'kia': [
{
'model': 'optima',
'year': '2012'
}
]
}
@metakungfu answer略有不同,主要区别在于它从结果对象中省略了原始键,因为在某些情况下对象本身不再需要它,因为它现在在父对象中可用。
const groupBy = (_k, a) => a.reduce((r, {[_k]:k, ...p}) => ({
...r, ...{[k]: (
r[k] ? [...r[k], {...p}] : [{...p}]
)}
}), {});
考虑到您的原始输入对象:
console.log(groupBy('make', cars));
会导致:
{
audi: [
{ model: 'r8', year: '2012' },
{ model: 'rs5', year: '2013' }
],
ford: [
{ model: 'mustang', year: '2012' },
{ model: 'fusion', year: '2015' }
],
kia: [
{ model: 'optima', year: '2012' }
]
}
使用lodash/fp,你可以使用_.flow()创建一个函数,它首先按键分组,然后映射每个组,并从每个项中省略一个键:
const { flow, groupBy, mapValues, map, omit } = _;
const groupAndOmitBy = key => flow(
groupBy(key),
mapValues(map(omit(key)))
);
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 groupAndOmitMake = groupAndOmitBy('make');
const result = groupAndOmitMake(cars);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src='https://cdn.jsdelivr.net/g/lodash@4(lodash.min.js+lodash.fp.min.js)'></script>
Prototype version using ES6 as well.
Basically this uses the reduce function to pass in an accumulator and current item, which then uses this to build your "grouped" arrays based on the passed in key. the inner part of the reduce may look complicated but essentially it is testing to see if the key of the passed in object exists and if it doesn't then create an empty array and append the current item to that newly created array otherwise using the spread operator pass in all the objects of the current key array and append current item. Hope this helps someone!.
Array.prototype.groupBy = function(k) {
return this.reduce((acc, item) => ((acc[item[k]] = [...(acc[item[k]] || []), item]), acc),{});
};
const projs = [
{
project: "A",
timeTake: 2,
desc: "this is a description"
},
{
project: "B",
timeTake: 4,
desc: "this is a description"
},
{
project: "A",
timeTake: 12,
desc: "this is a description"
},
{
project: "B",
timeTake: 45,
desc: "this is a description"
}
];
console.log(projs.groupBy("project"));
您正在寻找_.groupBy()。
如果需要,从对象中删除分组的属性应该很简单:
Const cars = [{
“做”:“奥迪”,
“模型”:“r8”,
“年”:“2012”
},{
“做”:“奥迪”,
“模型”:“生活费”,
“年”:“2013”
},{
“做”:“福特”,
“模型”:“野马”,
“年”:“2012”
},{
“做”:“福特”,
“模型”:“融合”,
“年”:“2015”
},{
“做”:“克钦独立军”,
“模型”:“最佳状态”,
“年”:“2012”
});
Const分组= _。groupBy(cars, car => car.make);
console.log(分组);
< script src = " https://cdn.jsdelivr.net/lodash/4.17.2/lodash.min.js " > < /脚本>
你也可以像这样使用数组#forEach()方法:
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' }];
let newcars = {}
cars.forEach(car => {
newcars[car.make] ? // check if that array exists or not in newcars object
newcars[car.make].push({model: car.model, year: car.year}) // just push
: (newcars[car.make] = [], newcars[car.make].push({model: car.model, year: car.year})) // create a new array and push
})
console.log(newcars);