将数组按指定键(如 city)分组并返回结构化数组(而非对象)

3次阅读

将数组按指定键(如 city)分组并返回结构化数组(而非对象)

本文详解如何使用 JavaScript 的 reduce() 方法,将原始数组按某个字段(如 city)归类,生成每个分组包含 city 和对应 data 子数组的规范结构,避免常见误区(如误用对象作为累加器导致返回非数组结果)。

本文详解如何使用 javascript 的 `reduce()` 方法,将原始数组按某个字段(如 `city`)归类,生成每个分组包含 `city` 和对应 `data` 子数组的规范结构,避免常见误区(如误用对象作为累加器导致返回非数组结果)。

在实际开发中,常需将扁平数组按某一属性(如地区、类别、状态等)聚合成带层级结构的数据,用于渲染分组列表、侧边导航或数据看板。但许多开发者初试 reduce() 时容易陷入一个典型陷阱:以空对象 {} 为初始值,虽能完成分组逻辑,最终却得到形如 { London: […], Manchester: […] } 的对象——而业务场景往往要求严格返回数组格式,且每个元素必须是统一结构的对象(含 city 字段与 data 数组),便于后续遍历、排序或与 ui 框架(如 React 列表渲染)直接对接。

正确做法是:始终以空数组 [] 作为 reduce 的初始累加器,并在每轮迭代中主动查找或创建目标分组对象,再向其 data 属性中追加当前项。以下是完整、可运行的实现:

const locations = [   { "city": "London", "district": "Brixton", "id": "Eue3uFjUHKi6wh73QZLX" },   { "city": "Manchester", "district": "Bury", "id": "QZiiUBgzZaJt2HcahELT" },   { "city": "London", "district": "Hackney", "id": "v2itdyO4IPXAMhIU8wce" } ];  const groupedLocations = locations.reduce((groups, item) => {   const { city } = item;    // 在已有的 groups 数组中查找是否存在同 city 的分组   const existingGroup = groups.find(group => group.city === city);    if (existingGroup) {     // 若存在,直接将当前 item 推入其 data 数组     existingGroup.data.push(item);   } else {     // 若不存在,新建分组对象并加入 groups 数组     groups.push({ city, data: [item] });   }    return groups; }, []); // ⚠️ 关键:初始值必须是 []  console.log(groupedLocations); // 输出符合预期的数组结构: // [ //   { city: "London", data: [ /* 两个 London 对象 */ ] }, //   { city: "Manchester", data: [ /* 一个 Manchester 对象 */ ] } // ]

关键要点总结

  • reduce() 的返回类型完全由回调函数每次 return 的值决定,因此初始值 [] + 每次 return groups 保证最终结果必为数组;
  • 使用 find() 查找已有分组比 Filter()[0] 更高效,避免重复遍历;
  • 新建分组时直接初始化 data: [item],比先 push({ city, data: [] }) 再 push(item) 更简洁;
  • 此方案天然支持任意键名(只需替换 city 为 item.category 或 item.status 等),扩展性强。

⚠️ 注意事项

  • 若原始数组极大(万级),find() 的线性查找可能影响性能;此时可先用 map 或对象做 O(1) 索引缓存,再转为数组输出(进阶优化);
  • 确保 city 值为字符串或可安全比较的类型,若含 NULL/undefined,建议提前校验或使用 String(item.city) 统一处理;
  • 如需保持分组顺序与首次出现顺序一致(如本例中 “London” 先于 “Manchester”),当前实现已天然满足;若需按字母序等规则排序,可在 reduce 后链式调用 .sort((a, b) => a.city.localeCompare(b.city))。

该方法简洁、可读、无外部依赖,是现代 JavaScript 中处理结构化分组任务的推荐实践。

text=ZqhQzanResources