Я хочу преобразовать массив в перегруппировку всех городов для одной страны. У меня есть массив объектов
locations = [
{
cities: ["Paris"]
country: "France"
},
{
cities: ["Marseille"]
country: "France"
},
{
cities: ["Kiev"]
country: "Ukraine"
},
{
cities: ["Odessa"]
country: "Ukraine"
}
...
И я хочу это:
locations = [
{
cities: ["Paris", "Marseille"]
country: "France"
},
{
cities: ["Kiev, Odessa"]
country: "Ukraine"
},
...
Итак, мое мышление таково:
locations.reduce((prev, curr) => {
if (prev.country === curr.country) {
prev.cities.push(curr.cities[0])
// and delete curr Object
}
})
Для первой пары равных стран curr.cities[0] помещается в prev.cities, но не для следующей итерации: TypeError: невозможно прочитать свойство «страна» неопределенного
[![console.info(locations) - TypeError: Невозможно прочитать свойство 'country' of undefined][1]][1]
вы не возвращаете prev из внутренней функции сокращения. поэтому в следующей итерации prev не существует.
При использовании уменьшить вам нужно вернуть prev
для использования в следующих итерациях, а также инициализировать его на {}
. Кроме того, вам нужно позаботиться о первоначальном добавлении каждой страны, в которой должен храниться объект с массивом cities
:
const locations = [
{ country: "France", cities: ['city1','city2'] },
{ country: "France", cities: ['city3','city4'] },
{ country: "Ukraine", cities: ['city5'] },
{ country: "Ukraine", cities: ['city6'] }
];
const res = Object.values(locations.reduce((prev, curr) => {
const { country, cities = [] } = curr;
const [city] = cities;
if (prev[country] && city) {
prev[country].cities.push(city);
} else {
prev[country] = { country, cities: city ? [city] : [] };
}
return prev;
}, {}));
console.info(res);
Я думаю, что для достижения желаемого формата вывода вы можете сделать что-то вроде этого:
locations = [
{ cities: ["Paris"], country: "France" },
{ cities: ["Marseille"], country: "France" },
{ cities: ["Kiev"], country: "Ukraine" },
{ cities: ["Odesa"], country: "Ukraine" }
];
var grouped = Object.entries(
locations.reduce((a, {country, cities}) => ({
...a, [country]: [...(a[country] || []), ...cities]
}), {})
).map(([country, cities]) => ({ country: country, cities: cities }), []);
console.info(grouped);
Вы можете создать карту с ключом по стране и с изначально пустым массивом в качестве соответствующего значения. Затем заполните эти массивы и, наконец, извлеките записи из этой карты. Это имеет линейную временную сложность:
let locations = [{cities: ["Paris"],country: "France"},{cities: ["Marseille"],country: "France"},{cities: ["Kiev"],country: "Ukraine"},{cities: ["Odesa"], country: "Ukraine"}];
let map = new Map(locations.map(({country}) => [country, {country, cities: []}]));
for (let loc of locations) map.get(loc.country).cities.push(...loc.cities);
let res = Array.from(map.values());
console.info(res);
Можете ли вы поделиться значениями в каждом массиве
cities
и результатом, который вы пытаетесь получить после преобразования объекта?