React 中使用 map 构建行列转置的动态表格(按类别聚合多日期数据)

本文介绍如何将嵌套 json 数据(按日期分组、每组含多类别)通过 react 的 map 方法重构为“类别为行、日期为列”的标准表格,解决原始渲染导致重复行的问题。

在 React 中渲染结构化表格时,若原始数据按时间维度嵌套(如每个日期对象包含多个类别子项),直接双层 map 会生成「日期 × 类别」的笛卡尔积式行结构,导致同一类别重复出现——这正是问题中表格错位的根本原因。要实现「类别为行、日期为列」的转置效果,关键在于先归一化数据,再按类别聚合跨日期值

✅ 正确的数据预处理流程

首先,将 category_evolution 扁平化为单一数据流,再按 category 分组构建映射表:

// 1. 合并所有日期下的 data 数组
const flatData = category_evolution.flatMap(item => item.data);

// 2. 按 category 归组:{ "Criptomoedas": [...], "REITs": [...], ... }
const categoryMap = flatData.reduce((acc, item) => {
  const { category } = item;
  if (!acc[category]) acc[category] = [];
  acc[category].push(item);
  return acc;
}, {});
? 推荐使用 flatMap 替代 reduce(...concat),语义更清晰;reduce 初始化为空对象 {},确保类型安全。

✅ 渲染转置表格(JSX)

表头保持原逻辑(日期列),但

需遍历 categoryMap 的每个键(即唯一类别),并在每行中按日期顺序取对应值:

      {category_evolution.map(({ name }) => (
        
      ))}
    
    {Object.keys(categoryMap).map(category => {
      const entries = categoryMap[category]; // 当前类别的所有日期记录
      return (
        
          {/* 按 category_evolution 原始顺序匹配日期,避免错位 */}
          {category_evolution.map(({ name }) => {
            const match = entries.find(item => item.date === name);
            return (
              
            );
          })}
        
      );
    })}
  
Categoria{name}
{category} {match ? match.category_total_brl : '-'}

⚠️ 注意事项与健壮性增强

  • 日期顺序一致性:category_evolution 的原始顺序决定了表头和数据列的对应关系,务必确保 item.date 字段与 name 完全一致(如 "01/02/2025"),否则 find() 将返回 undefined。
  • 空值容错:使用 match ? ... : '-' 防止某类别在某日期缺失时渲染 undefined。
  • 性能优化:若数据量大,可提前构建 dateToIndex 映射,将 find() 改为 O(1) 查找:
    const dateIndex = Object.fromEntries(
      category_evolution.map((item, i) => [item.name, i])
    );
    // 然后 entries[dateIndex[name]] 即可直接索引
  • 可扩展性:如需支持 USD 列,只需复制 并替换 category_total_usd 字段即可。

    通过这种「先归一、再分组、最后按序取值」的模式,你不仅能精准实现目标表格结构,还能轻松适配新增日期或类别,真正让 map 成为动态表格的可靠引擎。