Reputation: 1450
How would I turn an array of objects like this
const scores = [
{
year: 2020,
dave: 20
},
{
year: 2020,
steve: 17
},
{
year: 2019,
bill: 18
}
];
into this
const scores = [
{
year: 2020,
dave: 20,
steve: 17
},
{
year: 2019,
bill: 18
}
];
Upvotes: 0
Views: 57
Reputation: 191976
You can create a function with _.flow()
that uses _.groupBy()
to collect items with the same year
to arrays, and then maps and merges the arrays:
const { flow, groupBy, map, merge } = _;;
const fn = flow(
arr => groupBy(arr, 'year'),
groups => map(groups, g => merge({}, ...g))
);
const scores = [{"year":2020,"dave":20},{"year":2020,"steve":17},{"year":2019,"bill":18}];
const result = fn(scores);
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>
Using lodash/fp makes this solution even more concise:
const fn = flow(
groupBy('year'),
map(mergeAll)
);
const scores = [{"year":2020,"dave":20},{"year":2020,"steve":17},{"year":2019,"bill":18}];
const result = fn(scores);
console.log(result);
<script src='https://cdn.jsdelivr.net/g/lodash@4(lodash.min.js+lodash.fp.min.js)'></script>
However, since _.mergeBy()
creates an object, grouping by a number, will change the order of the groups (2020 after 2019). You can reduce the array to a Map to preserve the order, and then convert it to an array by spreading the Map's value iterator:
const scores = [{"year":2020,"dave":20},{"year":2020,"steve":17},{"year":2019,"bill":18}];
const result = [...scores.reduce((r, o) =>
r.set(o.year, { ...r.get(o.year), ...o })
, new Map()).values()];
console.log(result);
Upvotes: 0
Reputation: 833
Are you looking for this?
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
</head>
<body>
<script>
$(function () {
const scores = [
{
year: 2020,
dave: 20
},
{
year: 2020,
steve: 17
},
{
year: 2019,
bill: 18
}
];
var groupBy = function (xs, key) {
return xs.reduce(function (rv, x) {
(rv[x[key]] = rv[x[key]] || []).push(x);
return rv;
}, {});
};
console.log(groupBy(scores, 'year'));
})
</script>
</body>
</html>
Upvotes: 1
Reputation: 12960
I used an Array.reduce() and to have an Object with keys as year and kept assigning the Objects, later took out the values.
const scores = [
{
year: 2020,
dave: 20
},
{
year: 2020,
steve: 17
},
{
year: 2019,
bill: 18
}
];
const mergedOb = scores.reduce((acc, ob) => {
if (acc[ob.year]) {
Object.assign(acc[ob.year], ob);
} else {
acc[ob.year] = ob
}
return acc;
}, {});
const mergeArr = Object.values(mergedOb)
console.log(mergeArr)
Upvotes: 1