如何按city和country多键分组对象数组并生成子集数组?
按城市+国家分组JavaScript对象数组
我有如下JavaScript对象数组:
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'} ]
我希望将其按如下结构分组(注:示例中最后一个分组的item为笔误,以下实现统一使用items):
[ { 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', items: [ {city: 'Manchester', country: 'United States', date: '2024-02-03T00:00:00'}, {city: 'Manchester', country: 'United States', date: '2024-02-09T00:00:00'} ] } ]
我尝试了两种方法但都未成功:
第一种仅按城市分组,未考虑国家:
array.reduce((r, item) => { r[item.city] = r[item.city] || [] r[item.city].push(item) return r }, Object.create(null))
第二种逻辑存在问题,仅返回目标分组的第一个元素:
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); } }
现寻求正确的实现方案。
正确实现方案
核心思路是用city+country的组合作为唯一分组键,避免同名城市归属不同国家时的分组冲突,最后将分组对象转为目标数组结构。
方法一:使用Array.reduce实现
const grouped = Object.values(array.reduce((acc, item) => { // 拼接城市和国家作为唯一标识键 const key = `${item.city}_${item.country}`; if (!acc[key]) { acc[key] = { city: item.city, items: [] }; } acc[key].items.push(item); return acc; }, {})); console.log(grouped);
方法二:使用for...of循环实现
const groups = {}; for (const item of array) { const key = `${item.city}_${item.country}`; if (!groups[key]) { groups[key] = { city: item.city, items: [] }; } groups[key].items.push(item); } // 将分组对象的值转为数组,得到最终结构 const grouped = Object.values(groups); console.log(grouped);
说明
- 两种方法均通过
city与country的拼接字符串确保分组唯一性; - 最终用
Object.values()将分组对象转换为你需要的数组格式; - 修正了目标结构中的笔误,统一使用
items字段。
内容的提问来源于stack exchange,提问作者DessertEagle
相关产品推荐
相关产品推荐

