使用 reduce 转换数组(属性 未定义)
Transform array using reduce (property undefined)
我想转换一个数组以重新组合同一个国家/地区的所有城市。
我有一个 Object
数组
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,但不会用于下一次迭代:
类型错误:无法读取未定义的 属性 'country'
[![console.log(位置) - TypeError: 无法读取未定义的 属性 'country'[1]][1]
使用reduce
时,需要returnprev
才能在下一次迭代中使用,同时需要初始化为{}
。此外,您需要注意每个国家/地区的初始添加,其中应存储具有 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.log(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.log(grouped);
您可以创建一个按国家键控的地图,并使用一个初始为空的数组作为对应值。然后填充这些数组,最后从该 Map 中提取条目。这具有线性时间复杂度:
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.log(res);
我想转换一个数组以重新组合同一个国家/地区的所有城市。 我有一个 Object
数组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,但不会用于下一次迭代: 类型错误:无法读取未定义的 属性 'country'
[![console.log(位置) - TypeError: 无法读取未定义的 属性 'country'[1]][1]
使用reduce
时,需要returnprev
才能在下一次迭代中使用,同时需要初始化为{}
。此外,您需要注意每个国家/地区的初始添加,其中应存储具有 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.log(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.log(grouped);
您可以创建一个按国家键控的地图,并使用一个初始为空的数组作为对应值。然后填充这些数组,最后从该 Map 中提取条目。这具有线性时间复杂度:
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.log(res);