I have the following object:
const array = [
{city: 'Auckland', country: 'New Zealand', date: '2024-02-03T00:00:00'},
{city: 'Manchester', country: 'United Kingdom', date: '2024-02-04T00:00:00'},
{city: 'Manchester', country: 'United Kingdom', date: '2024-02-09T00:00:00'},
{city: 'Edinburgh', country: 'Scotland', date: '2024-02-05T00:00:00'},
{city: 'Manchester', country: 'United States', date: '2024-02-03T00:00:00'},
{city: 'Manchester', country: 'United States', date: '2024-02-09T00:00:00'}
]
I want it grouped like the following:
{
city: 'Auckland',
items: [
{city: 'Auckland', country: 'New Zealand', date: '2024-02-03T00:00:00'}
]
},
{
city: 'Manchester',
items: [
{city: 'Manchester', country: 'United Kingdom', date: '2024-02-04T00:00:00'},
{city: 'Manchester', country: 'United Kingdom', date: '2024-02-09T00:00:00'}
]
},
{
city: 'Edinburgh',
items: [
{city: 'Edinburgh', country: 'Scotland', date: '2024-02-05T00:00:00'}
]
},
{
city: 'Manchester',
item: [
{city: 'Manchester', country: 'United States', date: '2024-02-03T00:00:00'},
{city: 'Manchester', country: 'United States', date: '2024-02-09T00:00:00'}
]
}
I have tried multiple different methods. I scoured the net for a similar thread, especially on here but have not found a similar one. I've tried the following:
array.reduce((r, item) => {
r[item.city] = r[item.city] || []
r[item.city].push(item)
return r
}, Object.create(null))
However, this obviously does not take "country" into account. I've also tried the following but that only returns the first item in the desired group:
const cities = {};
for (let p of array) {
const { city, country } = p;
const groupByCity = JSON.stringify([city]);
const groupByCountry = JSON.stringify([country]);
if (!(groupByCity in cities)) {
cities[groupByCity] = { city: city, items: []};
cities[groupByCity].items.push(p);
} else if (groupByCity in examCities && cities[groupByCity].country !== p.country) {
cities[`${groupByCity}2`] = { city: city, items: []};
cities[`${groupByCity}2`].items.push(p);
}
}
CodePudding user response:
There are many ways to do this, here's my way by using reduce and map:
const array = [{
city: 'Auckland',
country: 'New Zealand',
date: '2024-02-03T00:00:00'
},
{
city: 'Manchester',
country: 'United Kingdom',
date: '2024-02-04T00:00:00'
},
{
city: 'Manchester',
country: 'United Kingdom',
date: '2024-02-09T00:00:00'
},
{
city: 'Edinburgh',
country: 'Scotland',
date: '2024-02-05T00:00:00'
},
{
city: 'Manchester',
country: 'United States',
date: '2024-02-03T00:00:00'
},
{
city: 'Manchester',
country: 'United States',
date: '2024-02-09T00:00:00'
}
]
const result = Object.entries(array.reduce((acc, curr) => {
const key = `${curr.city}|${curr.country}`
return {
...acc,
[key]: key in acc ? [...acc[key], curr] : [curr]
}
}, {})).map(([key, value]) => ({
city: value[0].city,
items: value
}))
console.log(result)
Basically I group them by {city}|{country}
and form an object with reduce
, then transform that object to the desired array with map
.