Reputation: 747
I have this nested array:
const users = [
['User_1', [[1596232800000, 4]]],
[
'User_2',
[
[1591567200000, 3],
[1591653600000, 16],
],
],
]
and would like this output:
const dataByDate = [
{
user: 'User_2',
date: 1591567200000,
count: 3,
},
{
user: 'User_2',
date: 1591653600000,
count: 16,
},
{
user: 'User_1',
date: 1596232800000,
count: 4,
},
]
To achieve this I am doing this:
const dataByDate: { date: string; count: number; user: string }[] = []
users.forEach((user: string[]) => {
if (user[1].length) {
user[1].forEach((item: any) => {
dataByDate.push({ date: item[0], user: user[0], count: item[1] })
})
}
})
My solution works fine but I am wondering if there is a cleaner and more elegant solution than a nested forEach. Thanks!
Upvotes: 1
Views: 429
Reputation: 50684
You can use .flatMap
with an inner .map()
. The inner .map()
will take the second element of your inner array (ie: the [[date, count], ...]
arrays), and map them to objects. Since .map()
will result in an array of objects, you can use .flatMap()
to merge the resulting objects into one final resulting array.
See example below:
const users = [
['User_1', [[1596232800000, 4]]],
[
'User_2',
[
[1591567200000, 3],
[1591653600000, 16],
],
],
];
const result = users.flatMap(([user, arr]) => arr.map(([date, count]) => ({
user, date, count
})));
console.log(result);
You can then apply the .sort()
method for any additional reordering of the output array.
Upvotes: 4
Reputation: 2614
Using map and array destructuring, you can achieve this as:
const result = users
.map(([ user, items ]) => {
return items.flatMap(([date, count]) => ({ user, date, count }))
})
.flatMap(i => i)
.sort((a,b) => a.date - b.date);
const users = [
['User_1', [[1596232800000, 4]]],
[
'User_2',
[
[1591567200000, 3],
[1591653600000, 16],
],
],
]
const result = users.map(([ user, items ]) => {
return items.flatMap(([date, count]) => ({ user, date, count }))
}).flatMap(i => i).sort((a,b) => a.date - b.date);
console.log({result})
Upvotes: 1
Reputation: 20934
Use a combination of Array.prototype.flatMap()
and Array.prototype.reduce()
. The reduce loops over each data set for a user and creates and object per entry in that set. That object is then combined in the accumulating array.
Now flatMap
returns a new array with objects for each user. The amount of objects are dependant on the amount of [date, count]
entries and will be in a nested array. The flat part of flatMap
takes care of this by putting every object in a single array.
const users = [
[
'User_1', [
[1596232800000, 4]
]
],
[
'User_2', [
[1591567200000, 3],
[1591653600000, 16],
],
],
];
const formatUserData = users => users.flatMap(([ user, data ]) =>
data.reduce((arr, [ date, count ]) =>
[...arr, { user, date, count }], [])
);
const result = formatUserData(users);
console.log(result);
Upvotes: 2