Reputation: 151
I'm trying to combine objects which share the same module key value, i.e. "credit cards". I need to return a single object per unique module with an array of distinct companies. The id and prod keys aren't important.
Here's the object I need to transform:
const data = [
{module: "credit_cards", id: "1", company: "ABC", prod: "1"},
{module: "credit_cards", id: "2", company: "XYZ", prod: "2"},
{module: "credit_cards", id: "3", company: "EFG", prod: "2"},
{module: "credit_cards", id: "2", company: "XYZ", prod: "2"},
{module: "mortgages", id: "4", company: "EFG", prod: "3"}
]
I need to return something like this:
const result = [
{module: "credit_cards", company: ["ABC", "XYZ", "EFG"]},
{module: "mortgages", company: ["EFG"]}
]
So far, I've tried this function:
const result = data.reduce(function(r, e) {
return Object.keys(e).forEach(function(k) {
if(!r[k]) r[k] = [].concat(e[k])
else r[k] = r[k].concat(e[k])
}), r
}, {})
But it just concatenated all the key/values together...
Any help would be awesome, thanks :)
Upvotes: 2
Views: 1877
Reputation: 26844
You can use reduce
to summarize the array into a Map
. Use Set
for unique values.
const data = [{"module":"credit_cards","id":"1","comapany":"ABC","prod":"1"},{"module":"credit_cards","id":"2","comapany":"XYZ","prod":"2"},{"module":"credit_cards","id":"3","comapany":"EFG","prod":"2"},{"module":"credit_cards","id":"2","comapany":"XYZ","prod":"2"},{"module":"mortgages","id":"4","comapany":"EFG","prod":"3"}]
const result = Array.from(data.reduce((c, {module,comapany}) => {
if (!c.has(module)) c.set(module, new Set);
c.get(module).add(comapany);
return c;
}, new Map)).map(([module, comapany]) => ({module,comapany: [...comapany]}));
console.log(result);
Upvotes: 3
Reputation: 408
const data = [
{module: 'credit_cards', id: '1', company: 'ABC', prod: '1'},
{module: 'credit_cards', id: '2', company: 'XYZ', prod: '2'},
{module: 'credit_cards', id: '3', company: 'EFG', prod: '2'},
{module: 'credit_cards', id: '2', company: 'XYZ', prod: '2'},
{module: 'mortgages', id: '4', company: 'EFG', prod: '3'}
];
const result = data.reduce((array, item) => {
const id = array.findIndex(el => el.module === item.module);
if (id > -1) {
array[id] = {...array[id], company : [...array[id].company, item.company]};
return array;
}
return [...array, {...item, company : [ item.company]}];
}, []);
Upvotes: 0
Reputation: 18515
Here is another approach with Array.reduce and with internal check to make sure the list of the companies is unique and without duplicates.
const data = [ {module: "credit_cards", id: "1", company: "ABC", prod: "1"}, {module: "credit_cards", id: "2", company: "XYZ", prod: "2"}, {module: "credit_cards", id: "3", company: "EFG", prod: "2"}, {module: "credit_cards", id: "2", company: "XYZ", prod: "2"}, {module: "mortgages", id: "4", company: "EFG", prod: "3"} ]
let result = data.reduce((r,{module, company}) => {
r[module] = r[module] || { module, company: [] }
if(!r[module].company.includes(company))
r[module].company.push(company)
return r
}, {})
console.log(Object.values(result))
Upvotes: 0
Reputation: 370699
Reduce into an object indexed by module
, then take that object's values. Because you only want unique company
values, use a Set initially, and then transform all items' company
sets back into an array afterwards:
const data = [
{module: "credit_cards", id: "1", company: "ABC", prod: "1"},
{module: "credit_cards", id: "2", company: "XYZ", prod: "2"},
{module: "credit_cards", id: "3", company: "EFG", prod: "2"},
{module: "credit_cards", id: "2", company: "XYZ", prod: "2"},
{module: "mortgages", id: "4", company: "EFG", prod: "3"}
]
const result = Object.values(data.reduce(
(a, { module, company }) => {
if (!a[module]) a[module] = { module, company: new Set() };
a[module].company.add(company);
return a;
},
{}
));
result.forEach((item) => {
item.company = [...item.company];
});
console.log(result);
Upvotes: 3
Reputation: 17190
You can use first Array.reduce() to group the companies
by the module
key on a Set. On a second step you can use array.Map() over the generated object .entries() to get the final desired result:
const data = [
{module: "credit_cards", id: "1", company: "ABC", prod: "1"},
{module: "credit_cards", id: "2", company: "XYZ", prod: "2"},
{module: "credit_cards", id: "3", company: "EFG", prod: "2"},
{module: "credit_cards", id: "2", company: "XYZ", prod: "2"},
{module: "mortgages", id: "4", company: "EFG", prod: "3"}
];
let res = data.reduce((acc, {module, company}) =>
{
acc[module] = acc[module] || new Set();
acc[module].add(company);
return acc;
}, {})
res = Object.entries(res).map(
([module, companies]) => ({module, company: [...companies]})
);
console.log(res);
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}
Upvotes: 3