You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular 13中如何将普通数组转为嵌套数组?求StackBlitz示例

在Angular 13中将一维数组按年份分组为嵌套数组

需求

需要将API返回的一维数据转换为按年份分组的嵌套结构,用于HTML循环渲染。

原始API数据

{
  "data": [
    {
      "Id": "17",
      "Year": "2020",
      "MonthName": "December",
      "Details": "Start the process ",
      "DisplayOrder": "3",
      "LanguageID": "1",
      "Hide": null
    },
    {
      "Id": "16",
      "Year": "2020",
      "MonthName": "August",
      "Details": "Conduct an online ",
      "DisplayOrder": "2",
      "LanguageID": "1",
      "Hide": null
    },
    {
      "Id": "15",
      "Year": "2020",
      "MonthName": "January",
      "Details": "Complete a minimum wage ",
      "DisplayOrder": "1",
      "LanguageID": "1",
      "Hide": null
    },
    {
      "Id": "12",
      "Year": "2019",
      "MonthName": "September",
      "Details": "Start professions",
      "DisplayOrder": "3",
      "LanguageID": "1",
      "Hide": null
    },
    {
      "Id": "11",
      "Year": "2019",
      "MonthName": "September",
      "Details": "Formulate Family Model",
      "DisplayOrder": "2",
      "LanguageID": "1",
      "Hide": null
    },
    {
      "Id": "13",
      "Year": "2019",
      "MonthName": "October",
      "Details": "Complete technical research",
      "DisplayOrder": "1",
      "LanguageID": "1",
      "Hide": null
    },
    {
      "Id": "14",
      "Year": "2019",
      "MonthName": "December",
      "Details": "Complete technical research service",
      "DisplayOrder": "1",
      "LanguageID": "1",
      "Hide": null
    },
    {
      "Id": "10",
      "Year": "2019",
      "MonthName": "September",
      "Details": "Formulate Occupation",
      "DisplayOrder": "1",
      "LanguageID": "1",
      "Hide": null
    },
    {
      "Id": "9",
      "Year": "2018",
      "MonthName": "October",
      "Details": "Approved officially",
      "DisplayOrder": "3",
      "LanguageID": "1",
      "Hide": null
    },
    {
      "Id": "8",
      "Year": "2018",
      "MonthName": "October",
      "Details": "Start technical research",
      "DisplayOrder": "2",
      "LanguageID": "1",
      "Hide": null
    },
    {
      "Id": "7",
      "Year": "2018",
      "MonthName": "October",
      "Details": "Publish a number completed",
      "DisplayOrder": "1",
      "LanguageID": "1",
      "Hide": null
    },
    {
      "Id": "6",
      "Year": "2017",
      "MonthName": "October",
      "Details": "Formulate Commission",
      "DisplayOrder": "5",
      "LanguageID": "1",
      "Hide": null
    },
    {
      "Id": "5",
      "Year": "2017",
      "MonthName": "May",
      "Details": "Complete the formulation",
      "DisplayOrder": "4",
      "LanguageID": "1",
      "Hide": null
    },
    {
      "Id": "4",
      "Year": "2017",
      "MonthName": "April",
      "Details": " Initiate relevant Act.",
      "DisplayOrder": "3",
      "LanguageID": "1",
      "Hide": null
    },
    {
      "Id": "3",
      "Year": "2017",
      "MonthName": "March",
      "Details": "Started the process employees",
      "DisplayOrder": "2",
      "LanguageID": "1",
      "Hide": null
    },
    {
      "Id": "2",
      "Year": "2017",
      "MonthName": "February",
      "Details": "Started the process allowances",
      "DisplayOrder": "1",
      "LanguageID": "1",
      "Hide": null
    },
    {
      "Id": "1",
      "Year": "2016",
      "MonthName": "October",
      "Details": "Members appointed",
      "DisplayOrder": "1",
      "LanguageID": "1",
      "Hide": null
    }
  ]
}

期望的嵌套数组结构

{
  "data": [
    {
      "Year": "2020",
      "Month": [
        {
          "Id": "17",
          "MonthName": "December",
          "Details": "Start the process",
          "DisplayOrder": "3",
          "LanguageID": "1",
          "Hide": null
        },
        {
          "Id": "16",
          "MonthName": "August",
          "Details": "Conduct an online",
          "DisplayOrder": "2",
          "LanguageID": "1",
          "Hide": null
        },
        {
          "Id": "15",
          "MonthName": "January",
          "Details": "Complete wage ",
          "DisplayOrder": "1",
          "LanguageID": "1",
          "Hide": null
        }
      ]
    },
    {
      "Year": "2019",
      "Month": [
        {
          "Id": "12",
          "MonthName": "September",
          "Details": "Start professions",
          "DisplayOrder": "3",
          "LanguageID": "1",
          "Hide": null
        },
        {
          "Id": "11",
          "MonthName": "September",
          "Details": "Formulate Family Model",
          "DisplayOrder": "2",
          "LanguageID": "1",
          "Hide": null
        },
        {
          "Id": "13",
          "MonthName": "October",
          "Details": "Complete technical research",
          "DisplayOrder": "1",
          "LanguageID": "1",
          "Hide": null
        },
        {
          "Id": "14",
          "MonthName": "December",
          "Details": "Complete technical research service",
          "DisplayOrder": "1",
          "LanguageID": "1",
          "Hide": null
        },
        {
          "Id": "10",
          "MonthName": "September",
          "Details": "Formulate Occupation",
          "DisplayOrder": "1",
          "LanguageID": "1",
          "Hide": null
        }
      ]
    },
    {
      "Year": "2018",
      "Month": [
        {
          "Id": "9",
          "MonthName": "October",
          "Details": "Approved officially",
          "DisplayOrder": "3",
          "LanguageID": "1",
          "Hide": null
        },
        {
          "Id": "8",
          "MonthName": "October",
          "Details": "Start technical research",
          "DisplayOrder": "2",
          "LanguageID": "1",
          "Hide": null
        },
        {
          "Id": "7",
          "MonthName": "October",
          "Details": "Publish a number completed",
          "DisplayOrder": "1",
          "LanguageID": "1",
          "Hide": null
        }
      ]
    },
    {
      "Year": "2017",
      "Month": [
        {
          "Id": "6",
          "MonthName": "October",
          "Details": "Formulate Commission",
          "DisplayOrder": "5",
          "LanguageID": "1",
          "Hide": null
        },
        {
          "Id": "5",
          "MonthName": "May",
          "Details": "Complete the formulation",
          "DisplayOrder": "4",
          "LanguageID": "1",
          "Hide": null
        },
        {
          "Id": "4",
          "MonthName": "April",
          "Details": " Initiate relevant Act.",
          "DisplayOrder": "3",
          "LanguageID": "1",
          "Hide": null
        },
        {
          "Id": "3",
          "MonthName": "March",
          "Details": "Started the process employees",
          "DisplayOrder": "2",
          "LanguageID": "1",
          "Hide": null
        },
        {
          "Id": "2",
          "MonthName": "February",
          "Details": "Started the process allowances",
          "DisplayOrder": "1",
          "LanguageID": "1",
          "Hide": null
        }
      ]
    },
    {
      "Year": "2016",
      "Month": [
        {
          "Id": "1",
          "MonthName": "October",
          "Details": "Members appointed",
          "DisplayOrder": "1",
          "LanguageID": "1",
          "Hide": null
        }
      ]
    }
  ]
}

实现方案

1. 定义数据接口

在组件中定义对应的数据类型,确保类型安全:

// 原始数据条目类型
interface OriginalTimelineItem {
  Id: string;
  Year: string;
  MonthName: string;
  Details: string;
  DisplayOrder: string;
  LanguageID: string;
  Hide: string | null;
}

// 分组后的月份条目类型
interface GroupedMonthItem {
  Id: string;
  MonthName: string;
  Details: string;
  DisplayOrder: string;
  LanguageID: string;
  Hide: string | null;
}

// 分组后的年份条目类型
interface GroupedYearItem {
  Year: string;
  Month: GroupedMonthItem[];
}

2. 数据分组逻辑

在组件的ngOnInit生命周期钩子中处理数据分组,使用Array.reduce按年份聚合数据,同时排序:

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-timeline',
  templateUrl: './timeline.component.html',
  styleUrls: ['./timeline.component.css']
})
export class TimelineComponent implements OnInit {
  // 模拟API返回的原始数据
  originalData: OriginalTimelineItem[] = [/* 原始数据数组,即上面的data内容 */];
  groupedData: GroupedYearItem[] = [];

  ngOnInit(): void {
    this.processGrouping();
  }

  processGrouping(): void {
    // 第一步:按年份分组
    const yearGroups = this.originalData.reduce((acc, item) => {
      const year = item.Year;
      // 构造月份条目,去掉Year字段
      const monthItem: GroupedMonthItem = {
        Id: item.Id,
        MonthName: item.MonthName,
        Details: item.Details.trim(), // 清理详情文本的首尾空格
        DisplayOrder: item.DisplayOrder,
        LanguageID: item.LanguageID,
        Hide: item.Hide
      };

      if (!acc[year]) {
        acc[year] = [];
      }
      acc[year].push(monthItem);
      return acc;
    }, {} as Record<string, GroupedMonthItem[]>);

    // 第二步:转换为数组并排序
    this.groupedData = Object.entries(yearGroups)
      .map(([year, months]) => ({
        Year: year,
        // 月份条目按DisplayOrder降序排列
        Month: months.sort((a, b) => parseInt(b.DisplayOrder) - parseInt(a.DisplayOrder))
      }))
      // 年份按降序排列(最新年份在前)
      .sort((a, b) => parseInt(b.Year) - parseInt(a.Year));
  }
}

3. HTML模板渲染

在组件模板中使用*ngFor嵌套循环渲染分组后的数据:

<div class="timeline-container">
  <div *ngFor="let yearGroup of groupedData" class="year-section">
    <h2>{{ yearGroup.Year }}</h2>
    <div class="month-list">
      <div *ngFor="let monthItem of yearGroup.Month" class="timeline-item">
        <h3>{{ monthItem.MonthName }}</h3>
        <p>{{ monthItem.Details }}</p>
        <span class="order-tag">排序: {{ monthItem.DisplayOrder }}</span>
      </div>
    </div>
  </div>
</div>

4. 基础样式(可选)

添加简单样式优化显示效果:

.timeline-container {
  max-width: 800px;
  margin: 2rem auto;
  padding: 0 1rem;
}

.year-section {
  margin-bottom: 2rem;
  border-bottom: 1px solid #eee;
  padding-bottom: 1rem;
}

.timeline-item {
  margin: 1rem 0;
  padding: 1rem;
  background-color: #f9f9f9;
  border-radius: 4px;
}

.order-tag {
  font-size: 0.8rem;
  color: #666;
}

StackBlitz示例说明

可以创建一个Angular 13项目,将上述代码对应放入:

  • src/app/timeline/timeline.component.ts:组件逻辑
  • src/app/timeline/timeline.component.html:模板代码
  • src/app/timeline/timeline.component.css:样式代码
  • 在app.module.ts中声明该组件,即可运行查看效果。

内容的提问来源于stack exchange,提问作者Anton96

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 01:40:32