JavaScript中按类别统计年份频次并生成堆叠折线图数据的方案求助
问题:统计类别年份频次并生成总计数据用于堆叠折线图
我正尝试在JavaScript中构建输入与目标输出数据的映射,统计每个类别下各年份的出现次数,同时生成总计数据以填充堆叠折线图(每条线对应一个类别,额外一条为总计)。
输入数据
const inputDates = [ { title: 'categoryOne', years: ['2021', '2021', '2023', '2022', '2022', '2021'] }, { title: 'categoryTwo', years: ['2021', '2022', '2022', '2022', '2022', '2023'] }, { title: 'categoryThree', years: ['2022', '2023', '2023'] }, ];
期望输出
const chartData = [ { title: 'categoryOne', years: [ {year: '2021', count: 3}, {year: '2022', count: 2}, {year: '2023', count: 1}, ] }, { title: 'categoryTwo', years: [ {year: '2021', count: 1}, {year: '2022', count: 4}, {year: '2023', count: 1}, ] }, { title: 'categoryThree', years: [ {year: '2022', count: 1}, {year: '2023', count: 2}, ] }, { title: 'total', years: [ {year: '2021', count: 4}, {year: '2022', count: 7}, {year: '2023', count: 4}, ] }, ];
实现思路与代码
1. 编写年份统计工具函数
先实现一个通用函数,接收年份数组,返回按{year, count}格式整理的统计结果:
function countYears(yearArray) { // 用reduce统计每个年份的出现次数 const countMap = yearArray.reduce((acc, year) => { acc[year] = (acc[year] || 0) + 1; return acc; }, {}); // 将统计对象转成目标数组格式 return Object.entries(countMap).map(([year, count]) => ({ year, count })); }
2. 处理所有类别数据
遍历输入数组,对每个类别调用工具函数,生成处理后的类别列表:
const processedCategories = inputDates.map(item => ({ title: item.title, years: countYears(item.years) }));
3. 计算总计数据
收集所有类别的年份统计结果,累加每个年份的总次数:
// 合并所有类别的统计数据,生成总计数映射 const totalCountMap = processedCategories.reduce((acc, category) => { category.years.forEach(({ year, count }) => { acc[year] = (acc[year] || 0) + count; }); return acc; }, {}); // 转成目标格式的总计数据 const totalData = { title: 'total', years: Object.entries(totalCountMap).map(([year, count]) => ({ year, count })) };
4. 合并最终结果
把处理后的类别数据和总计数据合并,得到最终的chartData:
const chartData = [...processedCategories, totalData];
完整代码
const inputDates = [ { title: 'categoryOne', years: ['2021', '2021', '2023', '2022', '2022', '2021'] }, { title: 'categoryTwo', years: ['2021', '2022', '2022', '2022', '2022', '2023'] }, { title: 'categoryThree', years: ['2022', '2023', '2023'] }, ]; function countYears(yearArray) { const countMap = yearArray.reduce((acc, year) => { acc[year] = (acc[year] || 0) + 1; return acc; }, {}); return Object.entries(countMap).map(([year, count]) => ({ year, count })); } const processedCategories = inputDates.map(item => ({ title: item.title, years: countYears(item.years) })); const totalCountMap = processedCategories.reduce((acc, category) => { category.years.forEach(({ year, count }) => { acc[year] = (acc[year] || 0) + count; }); return acc; }, {}); const totalData = { title: 'total', years: Object.entries(totalCountMap).map(([year, count]) => ({ year, count })) }; const chartData = [...processedCategories, totalData]; console.log(chartData);
内容的提问来源于stack exchange,提问作者Phil S
相关产品推荐
相关产品推荐

