I have a dataset like this:
[
{
"Happy": 1,
"createdAt": "2021-12-20"
},
{
"Tired": 1,
"createdAt": "2021-12-14"
},
{
"Energetic": 1,
"createdAt": "2021-12-13",
"Anxious": 1
},
{
"Energetic": 1,
"createdAt": "2021-12-13",
"Anxious": 1
},
{
"Tired": 1,
"createdAt": "2021-12-09",
"Anxious": 1
},
{
"Tired": 1,
"createdAt": "2021-12-09",
"Anxious": 1
},
{
"Sad": 1,
"createdAt": "2021-12-09"
},
{
"Sad": 1,
"createdAt": "2021-12-08"
},
{
"Happy": 1,
"createdAt": "2021-12-08"
},
{
"Anxious": 1,
"createdAt": "2021-12-08"
},
{
"Happy": 1,
"createdAt": "2021-12-08"
},
{
"Tired": 1,
"createdAt": "2021-12-08"
},
{
"Energetic": 1,
"createdAt": "2021-12-08"
},
{
"Anxious": 1,
"createdAt": "2021-12-08"
},
{
"Happy": 1,
"createdAt": "2021-12-08"
},
{
"Sad": 1,
"createdAt": "2021-12-08"
},
{
"Happy": 1,
"createdAt": "2021-12-08"
},
{
"Happy": 1,
"createdAt": "2021-12-08"
},
{
"Anxious": 1,
"createdAt": "2021-12-08"
},
{
"Sad": 1,
"createdAt": "2021-12-08"
},
{
"Anxious": 1,
"createdAt": "2021-12-08"
},
{
"Anxious": 1,
"createdAt": "2021-12-08"
},
{
"Tired": 1,
"createdAt": "2021-12-08"
},
{
"Anxious": 1,
"createdAt": "2021-12-08"
},
{
"Anxious": 1,
"createdAt": "2021-12-08"
}
]
What I want to do is group this by createdAt
and if there are duplicates keys within said date, add the duplicates together. For example:
{
"Energetic": 1,
"createdAt": "2021-12-13",
"Anxious": 1
},
{
"Energetic": 1,
"createdAt": "2021-12-13",
"Anxious": 1
},
will be
{
'Tired': 2,
'Anxious': 2,
'createdAt': '2021-12-13'
}
Another example:
{
"Sad": 1,
"createdAt": "2021-12-08"
},
{
"Happy": 1,
"createdAt": "2021-12-08"
},
{
"Anxious": 1,
"createdAt": "2021-12-08"
},
{
"Happy": 1,
"createdAt": "2021-12-08"
},
{
"Tired": 1,
"createdAt": "2021-12-08"
},
{
"Energetic": 1,
"createdAt": "2021-12-08"
},
{
"Anxious": 1,
"createdAt": "2021-12-08"
},
{
"Happy": 1,
"createdAt": "2021-12-08"
},
{
"Sad": 1,
"createdAt": "2021-12-08"
},
{
"Happy": 1,
"createdAt": "2021-12-08"
},
{
"Happy": 1,
"createdAt": "2021-12-08"
},
{
"Anxious": 1,
"createdAt": "2021-12-08"
},
{
"Sad": 1,
"createdAt": "2021-12-08"
},
{
"Anxious": 1,
"createdAt": "2021-12-08"
},
{
"Anxious": 1,
"createdAt": "2021-12-08"
},
{
"Tired": 1,
"createdAt": "2021-12-08"
},
{
"Anxious": 1,
"createdAt": "2021-12-08"
},
{
"Anxious": 1,
"createdAt": "2021-12-08"
}
will look like
{
'Sad': 3,
'Anxious': 7,
'Happy': 5,
'Tired': 2,
'Energetic': 1,
'createdAt': '2021-12-08',
}
I was able to get the dataset like this so far:
response.value.reduce((acc, val) => {
acc[toMoodMap(val) as string] = acc[val] === undefined ? 1 : (acc[val] += 1);
acc['createdAt'] = assessment.createdAt;
moodArr.push(acc);
return acc;
}, {});
I'm aware of lodash's groupBy, but it's currently not available to me unfortunately. Is there a way to achieve the end result?
Array#reduce
, iterate over the array while updating a Map
where createdAt
is the key and the grouped object is the value.
Map#get
, get the map value which key is the current createdAt
, otherwise a fallback object with createdAt
.Object#entries
and Array#forEach
, iterate over the rest of the current object's properties and increment the values.Map#set
, update the current pair.Map#values
, return the list of grouped objects by createdAt
. const arr = [ { "Sad": 1, "createdAt": "2021-12-08" }, { "Happy": 1, "createdAt": "2021-12-08" }, { "Anxious": 1, "createdAt": "2021-12-08" }, { "Happy": 1, "createdAt": "2021-12-08" }, { "Tired": 1, "createdAt": "2021-12-08" }, { "Energetic": 1, "createdAt": "2021-12-08" }, { "Anxious": 1, "createdAt": "2021-12-08" }, { "Happy": 1, "createdAt": "2021-12-08" }, { "Sad": 1, "createdAt": "2021-12-08" }, { "Happy": 1, "createdAt": "2021-12-08" }, { "Happy": 1, "createdAt": "2021-12-08" }, { "Anxious": 1, "createdAt": "2021-12-08" }, { "Sad": 1, "createdAt": "2021-12-08" }, { "Anxious": 1, "createdAt": "2021-12-08" }, { "Anxious": 1, "createdAt": "2021-12-08" }, { "Tired": 1, "createdAt": "2021-12-08" }, { "Anxious": 1, "createdAt": "2021-12-08" }, { "Anxious": 1, "createdAt": "2021-12-08" } ]; const res = [... arr.reduce((map, { createdAt, ...e }) => { const current = map.get(createdAt)?? { createdAt }; Object.entries(e).forEach(([key, value]) => current[key] = (current[key]?? 0) + value); map.set(createdAt, current); return map; }, new Map).values() ]; console.log(res);
assuming your array is called data
:
// let's create an object with keys equals to all created dates, values are all items with that date.
Object.values(data.reduce((res, item) => {
const groupedItem = Object.keys(item).reduce((group, key) => {
if (key === 'createdAt') {
return group;
}
const value = item[key];
if (isNaN(value)) { // if the value is not a number
return group;
}
return {
...group,
[key]: (group[key] || 0) + value,
};
}, res[item.createdAt] || {createdAt: item.createdAt});
return {
...res,
[item.createdAt]: groupedItem,
};
}, {}));
You were doing correct! You just want to obtain array from the final grouped object using Object.values
rather than pushing it inside .reduce
itself.
const arr = [
... Your Array
];
groupedItems = arr.reduce((acc, curr) => {
const key = curr["createdAt"];
if (!acc[key]) acc[key] = {}
for (let i in curr) {
if (i === "createdAt") {
acc[key][i] = curr[i]
} else {
acc[key][i] = (acc[key][i] || 0) + 1
}
}
return acc;
}, {});
console.log(Object.values(groupedItems))
I would do this manually.
First, break it down by extracting all the different createdAt's (into a set to avoid duplicates). Then, for each createdAt, get all the existing keys. For each key, count the occurrences.
Here is the beginning of the code, how I would do it. I hope this already helps, I have no time to finish that code up right now, but let me know it you are able to do it with this approach.
Code:
const data = [
{
"Happy": 1,
"createdAt": "2021-12-20"
},
{
"Tired": 1,
"createdAt": "2021-12-14"
},
{
"Energetic": 1,
"createdAt": "2021-12-13",
"Anxious": 1
},
{
"Energetic": 1,
"createdAt": "2021-12-13",
"Anxious": 1
},
{
"Tired": 1,
"createdAt": "2021-12-09",
"Anxious": 1
},
{
"Tired": 1,
"createdAt": "2021-12-09",
"Anxious": 1
},
{
"Sad": 1,
"createdAt": "2021-12-09"
},
{
"Sad": 1,
"createdAt": "2021-12-08"
},
{
"Happy": 1,
"createdAt": "2021-12-08"
},
{
"Anxious": 1,
"createdAt": "2021-12-08"
},
{
"Happy": 1,
"createdAt": "2021-12-08"
},
{
"Tired": 1,
"createdAt": "2021-12-08"
},
{
"Energetic": 1,
"createdAt": "2021-12-08"
},
{
"Anxious": 1,
"createdAt": "2021-12-08"
},
{
"Happy": 1,
"createdAt": "2021-12-08"
},
{
"Sad": 1,
"createdAt": "2021-12-08"
},
{
"Happy": 1,
"createdAt": "2021-12-08"
},
{
"Happy": 1,
"createdAt": "2021-12-08"
},
{
"Anxious": 1,
"createdAt": "2021-12-08"
},
{
"Sad": 1,
"createdAt": "2021-12-08"
},
{
"Anxious": 1,
"createdAt": "2021-12-08"
},
{
"Anxious": 1,
"createdAt": "2021-12-08"
},
{
"Tired": 1,
"createdAt": "2021-12-08"
},
{
"Anxious": 1,
"createdAt": "2021-12-08"
},
{
"Anxious": 1,
"createdAt": "2021-12-08"
}
]
const createdAts = new Set()
data.forEach(datum => {
createdAts.add(datum.createdAt);
});
const dataTranformed = [];
createdAts.forEach(createdAt => {
// This array contains all data entries, for one createdAt-date
const dataFiltered = data.filter((datum) => datum.createdAt === createdAt);
// Here you will have to create a new object and add all the keys & values from dataFiltered (&increment numbers if an key already exists)
// Add this Object to the dataTransformed list and you are done
});
You could group by destructured createdAt
and collect count for each key/value pair of the rest object.
const data = [{ Happy: 1, createdAt: "2021-12-20" }, { Tired: 1, createdAt: "2021-12-14" }, { Energetic: 1, createdAt: "2021-12-13", Anxious: 1 }, { Energetic: 1, createdAt: "2021-12-13", Anxious: 1 }, { Tired: 1, createdAt: "2021-12-09", Anxious: 1 }, { Tired: 1, createdAt: "2021-12-09", Anxious: 1 }, { Sad: 1, createdAt: "2021-12-09" }, { Sad: 1, createdAt: "2021-12-08" }, { Happy: 1, createdAt: "2021-12-08" }, { Anxious: 1, createdAt: "2021-12-08" }, { Happy: 1, createdAt: "2021-12-08" }, { Tired: 1, createdAt: "2021-12-08" }, { Energetic: 1, createdAt: "2021-12-08" }, { Anxious: 1, createdAt: "2021-12-08" }, { Happy: 1, createdAt: "2021-12-08" }, { Sad: 1, createdAt: "2021-12-08" }, { Happy: 1, createdAt: "2021-12-08" }, { Happy: 1, createdAt: "2021-12-08" }, { Anxious: 1, createdAt: "2021-12-08" }, { Sad: 1, createdAt: "2021-12-08" }, { Anxious: 1, createdAt: "2021-12-08" }, { Anxious: 1, createdAt: "2021-12-08" }, { Tired: 1, createdAt: "2021-12-08" }, { Anxious: 1, createdAt: "2021-12-08" }, { Anxious: 1, createdAt: "2021-12-08" }], result = Object.values(data.reduce((r, { createdAt, ...o }) => { r[createdAt]??= { createdAt }; Object.entries(o).forEach(([k, v]) => r[createdAt][k] = (r[createdAt][k] || 0) + v); return r; }, {})); console.log(result);
.as-console-wrapper { max-height: 100%;important: top; 0; }
lets say your this is your array below
let arr = [ ... ];
Then we filter the object with date grouped as keys
const g = arr.reduce((a, c) => {
let date = c.createdAt;
if(!a[date]) {
a[date] = [];
}
a[date].push(c);
return a;
}, {});
return the filtered object as array with the generated array...
const groupedByDate = Object.keys(g).map(dt => {
return { date:dt, values: g[dt] };
});
console.log(groupedByDate);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.