Most Efficient Method to Groupby on an Array of Objects

Most efficient method to groupby on an array of objects

If you want to avoid external libraries, you can concisely implement a vanilla version of groupBy() like so:

var groupBy = function(xs, key) {
return xs.reduce(function(rv, x) {
(rv[x[key]] = rv[x[key]] || []).push(x);
return rv;
}, {});
};

console.log(groupBy(['one', 'two', 'three'], 'length'));

// => {3: ["one", "two"], 5: ["three"]}

How can I group an array of objects by key?

Timo's answer is how I would do it. Simple _.groupBy, and allow some duplications in the objects in the grouped structure.

However the OP also asked for the duplicate make keys to be removed. If you wanted to go all the way:

var grouped = _.mapValues(_.groupBy(cars, 'make'),
clist => clist.map(car => _.omit(car, 'make')));

console.log(grouped);

Yields:

{ audi:
[ { model: 'r8', year: '2012' },
{ model: 'rs5', year: '2013' } ],
ford:
[ { model: 'mustang', year: '2012' },
{ model: 'fusion', year: '2015' } ],
kia:
[ { model: 'optima', year: '2012' } ]
}

If you wanted to do this using Underscore.js, note that its version of _.mapValues is called _.mapObject.

How to group items in an array by property using reduce and return an array of new objects

You should be able to do this in a few lines using reduce, we create a map using the Subdomain name as the key, then we'll use Object.values to turn the resulting object into an array.

For example:

const relatedSites = [ { "SubdomainName": "client1", "ClientName": "Eastern Region", "ClientAlias": "eastern-region" }, { "SubdomainName": "client1", "ClientName": "City of Knox", "ClientAlias": "knox" }, { "SubdomainName": "client2", "ClientName": "Eastern Region", "ClientAlias": "eastern-region" }, { "SubdomainName": "client2", "ClientName": "City of Knox", "ClientAlias": "knox" } ]; 

const result = Object.values(relatedSites.reduce((acc, el) => {
acc[el.SubdomainName] = acc[el.SubdomainName] || { title: el.SubdomainName, links: [] };
acc[el.SubdomainName].links.push({ url: `https://${el.SubdomainName}.com/${el.ClientAlias}`, displayText: el.ClientName });
return acc;
}, {}))

console.log(result)

Can anyone suggest of a way to group an array of objects by an object key then create a new array of objects based on the grouping in JavaScript?

You can efficiently achieve the result using Map and reduce

const arr = [
{
date: "2020-12-31T18:30:00.000Z",
value: 450,
},
{
date: "2020-12-31T18:30:00.000Z",
value2: 362,
},
{
date: "2020-12-31T18:30:00.000Z",
value3: 699,
},
{
date: "2021-03-01T18:30:00.000Z",
value: 269,
},
{
date: "2021-03-01T18:30:00.000Z",
value2: 450,
},
{
date: "2021-03-02T18:30:00.000Z",
value3: 841,
},
{
date: "2021-04-03T18:30:00.000Z",
value: 700,
},
];

const dict = arr.reduce((acc, curr) => {
const { date, ...rest } = curr;
if (!acc.has(date)) {
acc.set(date, curr);
} else {
const o = acc.get(curr.date);
Object.entries(curr).forEach(([k, v]) => (o[k] = v));
}
return acc;
}, new Map());

const result = [...dict.values()];

console.log(result);
/* This is not a part of answer. It is just to give the output full height. So IGNORE IT */

.as-console-wrapper {
max-height: 100% !important;
top: 0;
}

need to group objects, in array of objects, in one group

const data = [
{amount: 100, percent: 1, days: 7},
{amount: 75, percent: 3, days: 8},
{amount: 75, percent: 3, days: 3},
{amount: 100, percent: 2, days: 5},
{amount: 100, percent: 1, days: 10},
{amount: 50, percent: 3, days: 9}
];

const temp = data.reduce((acc, {amount, percent, days}) => {
acc[amount] ||= {}
acc[amount][percent] ||= 0
acc[amount][percent] += days
return acc;
}
,{});

const result = Object.entries(temp).reduce((acc, [amount, obj]) => {
acc.push(...Object.entries(obj).map(([percent, days]) => ({ amount: Number(amount), percent: Number(percent), days })))
return acc
},[])

console.log(result)

How to create a vanilla groupBy so that it returns an array of objects that have a title?

You can update your groupBy function as below to get the desired output.
Get the output of the current output with Object.entries and map to an array again.

const data = [ { CS_NAME: "AAA", IS_MAIN: "Y", WEBSITE_CREATE_DATE: "2021-06-01T15:50:37.687", }, { CS_NAME: "AAA", IS_MAIN: "N", WEBSITE_CREATE_DATE: "2021-08-03T12:02:58.07", }, { CS_NAME: "BBB", IS_MAIN: "Y", WEBSITE_CREATE_DATE: "2021-08-03T12:02:58.07", }, { CS_NAME: "BBB", IS_MAIN: "N", WEBSITE_CREATE_DATE: "2019-01-26T00:00:00", }, { CS_NAME: "CCC", IS_MAIN: "Y", WEBSITE_CREATE_DATE: "2019-01-26T00:00:00", }, ];

const groupBy = (input, key) => {
return Object.entries(
input.reduce((acc, currentValue) => {
let groupKey = currentValue[key];
if (!acc[groupKey]) {
acc[groupKey] = [];
}
acc[groupKey].push(currentValue);
return acc;
}, {})
).map(([title, content]) => ({ title, content }));
};

const obj = groupBy(data, "CS_NAME");

console.log(obj);


Related Topics



Leave a reply



Submit