有人知道一种方法(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'
}
]
}
对于key可以为null的情况,我们希望将它们分组为其他
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'},
{'make':'kia','model':'optima','year':'2033'},
{'make':null,'model':'zen','year':'2012'},
{'make':null,'model':'blue','year':'2017'},
];
result = cars.reduce(function (r, a) {
key = a.make || 'others';
r[key] = r[key] || [];
r[key].push(a);
return r;
}, Object.create(null));
只需简单的forEach循环就可以在这里工作,不需要任何库
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'
},
];
let ObjMap ={};
cars.forEach(element => {
var makeKey = element.make;
if(!ObjMap[makeKey]) {
ObjMap[makeKey] = [];
}
ObjMap[makeKey].push({
model: element.model,
year: element.year
});
});
console.log(ObjMap);
同意除非经常使用这些库,否则不需要外部库。虽然有类似的解决方案,但我发现其中一些很难遵循。如果您试图理解正在发生的事情,这里有一个带有注释的解决方案的要点。
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'
}, ];
/**
* Groups an array of objects by a key an returns an object or array grouped by provided key.
* @param array - array to group objects by key.
* @param key - key to group array objects by.
* @param removeKey - remove the key and it's value from the resulting object.
* @param outputType - type of structure the output should be contained in.
*/
const groupBy = (
inputArray,
key,
removeKey = false,
outputType = {},
) => {
return inputArray.reduce(
(previous, current) => {
// Get the current value that matches the input key and remove the key value for it.
const {
[key]: keyValue
} = current;
// remove the key if option is set
removeKey && keyValue && delete current[key];
// If there is already an array for the user provided key use it else default to an empty array.
const {
[keyValue]: reducedValue = []
} = previous;
// Create a new object and return that merges the previous with the current object
return Object.assign(previous, {
[keyValue]: reducedValue.concat(current)
});
},
// Replace the object here to an array to change output object to an array
outputType,
);
};
console.log(groupBy(cars, 'make', true))
我用REAL GROUP BY作为JS数组的例子和这个任务完全一样
const inputArray = [
{ Phase: "Phase 1", Step: "Step 1", Task: "Task 1", Value: "5" },
{ Phase: "Phase 1", Step: "Step 1", Task: "Task 2", Value: "10" },
{ Phase: "Phase 1", Step: "Step 2", Task: "Task 1", Value: "15" },
{ Phase: "Phase 1", Step: "Step 2", Task: "Task 2", Value: "20" },
{ Phase: "Phase 2", Step: "Step 1", Task: "Task 1", Value: "25" },
{ Phase: "Phase 2", Step: "Step 1", Task: "Task 2", Value: "30" },
{ Phase: "Phase 2", Step: "Step 2", Task: "Task 1", Value: "35" },
{ Phase: "Phase 2", Step: "Step 2", Task: "Task 2", Value: "40" }
];
var outObject = inputArray.reduce(function(a, e) {
// GROUP BY estimated key (estKey), well, may be a just plain key
// a -- Accumulator result object
// e -- sequentally checked Element, the Element that is tested just at this itaration
// new grouping name may be calculated, but must be based on real value of real field
let estKey = (e['Phase']);
(a[estKey] ? a[estKey] : (a[estKey] = null || [])).push(e);
return a;
}, {});
console.log(outObject);