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
The Create-React-App Imports Restriction Outside of Src Directory
Stretch Height to Fit Content in React Native
Using Thymeleaf Variable in Onclick Attribute
Concatenate Json to a String in JavaScript
Image Taken from Camera Not Saved to Gallery
Onclick JavaScript to Make Browser Go Back to Previous Page
How to Bind on Click Event on Dynamically Created Button in Angular 6
How to Clear Browsing History Using JavaScript
How Could I Get the Latest Date from an Array of Dates - Javascript/Typescript
How to Download Pdf Automatically Using Js
Show Virtual Keyboard on Mobile Phones in JavaScript
Check If Image Exists on Server Using JavaScript
How to Create Expand/Collapse Function for Each Row of Table - Angular6
What Does This Format Means T00:00:00.000Z
Print Pdf Directly from JavaScript
How to Correctly Use Axios Params With Arrays
Regular Expression to Accept Only Positive Numbers and Decimals