Reputation: 547
I have a single array of objects and I would like to reduce it down to another array of objects based on two keys value pairs.
const original =
[
{
key1: 'a',
key2: 'AA',
value: 1
},
{
key1: 'a',
key2: 'AA',
anotherValue: 2
},
{
key1: 'b',
key2: 'BB',
value: 1
},
{
key1: 'a',
key2: 'AA',
yetAnother: 3
},
{
key1: 'b',
key2: 'BB',
anotherValue: 4
},
{
key1: 'c',
key2: 'CC',
value: 1
}
];
Should be transformed into:
const result =
[
{
key1: 'a',
key2: 'AA',
value: 1,
anotherValue: 2,
yetAnother: 3
},
{
key1: 'b',
key2: 'BB',
value: 1,
anotherValue: 4
},
{
key1: 'c',
key2: 'CC',
value: 1
},
];
Tired using map and reduce and even lodash. However, all my attempts were futile.
Upvotes: 0
Views: 987
Reputation: 164736
Using Array.prototype.reduce()
, build up a Map
of entries, keyed by the combination of any key*
properties while merging in the other properties.
Then you can convert the Map
values into a new array
const original = [{"key1":"a","key2":"AA","value":1},{"key1":"a","key2":"AA","anotherValue":2},{"key1":"b","key2":"BB","value":1},{"key1":"a","key2":"AA","yetAnother":3},{"key1":"b","key2":"BB","anotherValue":4},{"key1":"c","key2":"CC","value":1}]
const t1 = performance.now()
const result = [...original.reduce((map, obj) => {
// create a key from all the "key*" properties
const key = Object.keys(obj)
.filter(key => key.startsWith("key"))
.sort()
.map(key => obj[key]).join(":") // looks like "a:AA", "b:BB", etc
// merge with previously found matches
const entry = {
...(map.get(key) ?? {}),
...obj
}
// collect the merged object
return map.set(key, entry)
}, new Map()).values()]
const t2 = performance.now()
console.info(result, `in ${t2 - t1}ms`)
.as-console-wrapper { max-height: 100% !important; }
Upvotes: 0
Reputation: 10193
Using Array.reduce
, you can group the objects by key1
and key2
value pairs.
And the variable groupBy
object values contain the result you want and you can generate the values only using Object.values(groupBy)
.
const original = [
{ key1: 'a', key2: 'AA', value: 1 },
{ key1: 'a', key2: 'AA', anotherValue: 2 },
{ key1: 'b', key2: 'BB', value: 1 },
{ key1: 'a', key2: 'AA', yetAnother: 3 },
{ key1: 'b', key2: 'BB', anotherValue: 4 },
{ key1: 'c', key2: 'CC', value: 1 }
];
const groupBy = original.reduce((acc, cur) => {
const { key1, key2, ...rest } = cur;
const key = key1 + "_" + key2;
acc[key] ? acc[key] = { ...acc[key], ...rest } : acc[key] = cur;
return acc;
}, {});
const result = Object.values(groupBy);
console.log(result);
Upvotes: 2