Maybe it’s easier - at least I think - to do without reduce
. Just make a loop simple by array old
and go riding the new object:
const old = [
{ id: 1, date: '2020-08-27T00:00:00', title: 'Title 1' },
{ id: 2, date: '2020-08-27T00:00:00', title: 'Title 2' },
{ id: 3, date: '2020-08-25T00:00:00', title: 'Title 3' }
];
let items = {};
for (let i = 0; i < old.length; i++) {
const e = old[i];
const novoItem = { id: e.id, title: e.title};
if (! items[e.date]) { // ainda não tem nada nesta data, criar um novo
items[e.date] = { date: e.date, children: [ novoItem ]};
} else { // já existe registro para a data, adiciona no array children já existente
items[e.date].children.push(novoItem);
}
}
console.log(items);
// ou, se quiser que items seja um array:
items = Object.values(items);
console.log(items);
That is, for each element in old
I check if there is already an element corresponding to your date in items
. If not, I create a new one, if I’ve already added it in the array children
.
It just wasn’t clear which way to go, so I gave you two options. The first is an object whose keys are the dates and values are the objects containing the date and array of children
:
{
"2020-08-27T00:00:00": {
"date": "2020-08-27T00:00:00",
"children": [
{ "id": 1, "title": "Title 1" },
{ "id": 2, "title": "Title 2" }
]
},
"2020-08-25T00:00:00": {
"date": "2020-08-25T00:00:00",
"children": [
{ "id": 3, "title": "Title 3" }
]
}
}
But in this case the date would be redundant. If the idea is to have an array (as it seems in the question example), just take only the values (Object.values(items)
), and in that case would be:
[
{
"date": "2020-08-27T00:00:00",
"children": [
{ "id": 1, "title": "Title 1" },
{ "id": 2, "title": "Title 2" }
]
},
{
"date": "2020-08-25T00:00:00",
"children": [
{ "id": 3, "title": "Title 3" }
]
}
]
If you want, you can also change the for
above by a for...of
:
for (const e of old) {
const novoItem = { id: e.id, title: e.title};
if (! items[e.date]) { // ainda não tem nada nesta data, criar um novo
items[e.date] = { date: e.date, children: [ novoItem ]};
} else { // já existe registro para a data, adiciona no array children já existente
items[e.date].children.push(novoItem);
}
}
Or still, using allocation via structuring together with the scattering syntax:
let items = {};
for (const e of old) {
const { date, ...novoItem } = { ...e };
if (! items[date]) {
items[date] = { date, children: [ novoItem ]};
} else {
items[date].children.push(novoItem);
}
}
Do you really need reduce
? It would look almost the same, but perhaps adding unnecessary complexity:
const old = [
{ id: 1, date: '2020-08-27T00:00:00', title: 'Title 1' },
{ id: 2, date: '2020-08-27T00:00:00', title: 'Title 2' },
{ id: 3, date: '2020-08-25T00:00:00', title: 'Title 3' }
];
let items = old.reduce(function(acc, item) {
const newItem = { id: item.id, title: item.title };
if (!acc[item.date]) {
acc[item.date] = { date: item.date, children: [ newItem ] };
} else {
acc[item.date].children.push(newItem);
}
return acc;
}, {});
console.log(items);
// ou, se quiser que items seja um array:
items = Object.values(items);
console.log(items);
I don’t think you need reduce
. Although the algorithm looks good, it adds a complexity that, although not so great so, in my opinion is unnecessary (create a function of callback which is called several times). If a for
simple already solves, so that complicate?
<pedant mode>I also changed the name of the childrens
for children
, after all, "Children" is already in the plural.</pedantic mode>
You already have a separate object, now you just need to use something like
Object.entries
with amap
then turn the object into an array in the format you need. :)– Luiz Felipe
Maybe this question can give you a general idea of how to do this. There are good alternatives there.
– Luiz Felipe