Reputation: 1223
Say I have an array of objects like so:
[{name: John, year: 2011, age: "65+", value: 2},
{name: John, year: 2012, age: "65+", value: 5},
{name: Bob, year: 2011, age: "18 under", value: 2}]
I'd like to convert this array of objects into the following:
[{name: John, age: "65+", 2011: 2, 2012: 5},
{name: Bob, age: "18 under", 2011: 2, 2012: NA}]
You'll notice that I've converted the year values into actual keys. How do I go about this efficiently?
Upvotes: 0
Views: 85
Reputation: 386550
You could group the data and collect all keys and apply later the missing years.
var data = [{ name: 'John', year: 2011, age: "65+", value: 2 }, { name: 'John', year: 2012, age: "65+", value: 5 }, { name: 'Bob', year: 2011, age: "18 under", value: 2 }],
years = new Set;
result = Object
.values(data.reduce((r, { name, year, value, ...o }) => {
r[name] = r[name] || { name, ...o };
r[name][year] = value;
years.add(year);
return r;
}, {}))
.map(
(y => o => ({ ...y, ...o }))
(Object.fromEntries([...years].map(y => [y, NaN])))
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 2
Reputation: 224857
You can do it by processing the array one element at a time and creating a new object every time you see a new name:
function* groupByName(entries) {
let group = null;
for (const {name, year, value} of entries) {
if (group === null || group.name !== name) {
if (group !== null) {
yield group;
}
group = {name};
}
group[year] = value;
}
if (group !== null) {
yield group;
}
}
const entries = [
{name: 'John', year: 2011, value: 2},
{name: 'John', year: 2012, value: 5},
{name: 'Bob', year: 2011, value: 2},
];
console.log([...groupByName(entries)]);
Upvotes: 0