新闻元数据多维度统计及结果按标签排序技术咨询
新闻推送应用元数据统计需求与问题解决
需求背景
我有一款新闻推送应用,会从其他站点拉取JSON格式的数据,仅需汇总各类元数据用于后续性能评估,不关注文章实际内容。
源数据
let articles = [ {id: "0",title: "article 1",tags: ["110"],source: "Company A", countries:["USA","CAN"]}, {id: "1",title: "article 2",tags: ["120","160","100"],source: "Company B", countries:["USA","CHN"]}, {id: "2",title: "article 3",tags: ["130","150"],source: "Company C", countries:["USA"]}, {id: "3",title: "article 4",tags: ["140","120","110","130"],source: "Company A", countries:["JPN","IRE"]}, {id: "4",title: "article 5",tags: ["110","130"],source: "Company C", countries:["SWE"]}, ]
期望输出
按来源统计结果
let output = [ {source: "Company A",tags:[{code:"110",count:2},{code:"140",count:1},{code:"120",count:1},{code:"130",count:1}],countries:[{code:"USA",count:1},{code:"CAN",count:1},{code:"JPN",count:1},{code:"IRE",count:1}]}, {source: "Company B",tags:[{code:"120",count:1},{code:"160",count:1},{code:"100",count:1}],countries:[{code:"USA",count:1},{code:"CHN",count:1}]}, {source: "Company C",tags:[{code:"110",count:2},{code:"130",count:2},{code:"150",count:1}],countries:[{code:"USA",count:1},{code:"SWE",count:1}]} ]
按标签统计结果(需按标签数字顺序排序)
let output2 = [ {tag:"110",sources:[{source:"Company A",count:2},{source:"Company C",count:1}],countries:[{country:"USA",count:1},{country:"CAN",count:1},{country:"SWE",count:1}]}, {tag:"120",sources:[{source:"Company A",count:1},{source:"Company B",count:1}],countries:[{country:"USA",count:1},{country:"CHN",count:1},{country:"JPN",count:1},{country:"IRE",count:1}]}, {tag:"130",sources:[{source:"Company A",count:1},{source:"Company C",count:1}],countries:[{country:"USA",count:1},{country:"SWE",count:1}]}, {tag:"140",sources:[{source:"Company A",count:1}],countries:[{country:"JPN",count:1},{country:"IRE",count:1}]}, {tag:"150",sources:[{source:"Company C",count:1}],countries:[{country:"USA",count:1}]}, {tag:"160",sources:[{source:"Company B",count:1}],countries:[{country:"USA",count:1},{country:"CHN",count:1}]}, {tag:"100",sources:[{source:"Company B",count:1}],countries:[{country:"USA",count:1},{country:"CHN",count:1}]} ]
初始思路与顾虑
最初考虑用三个Set分别存储标签、国家和来源,再基于这些集合构建对象并迭代统计,但担心扩展性——文章数量可达100-5000条,单篇文章标签1-10+个、国家1-50+个。相关代码:
tags = new Set(); countries = new Set(); sources = new Set(); articles.forEach(item =>{ item.tags.forEach(element =>{ tags.add(element); }) }) articles.forEach(item =>{ item.countries.forEach(element =>{ countries.add(element); }) }) articles.forEach(item =>{ sources.add(item.source); })
现有Map实现与问题
目前已经用Map实现了统计逻辑,但不知道在哪里添加排序逻辑,让按标签统计的结果按标签数字顺序排列。现有代码:
按标签统计代码
//-----By Tag------// articles.forEach((a) => { a.tags.forEach((tag) => { if (!tags.has(tag)) tags.set(tag, { sources: new Map(), countries: new Map() }); tags.get(tag).sources.set(a.source, (tags.get(tag).sources.get(a.source) ?? 0) + 1); a.countries.forEach((c) => { tags.get(tag).countries.set(c, (tags.get(tag).countries.get(c) ?? 0) + 1); }); }); }); const result = Array.from(tags) .map(([tag, { sources, countries }]) => ({ tag, sources: Array.from(sources).map(([source, count]) => ({ source, count })), countries: Array.from(countries).map(([country, count]) => ({ country, count })), })); console.log(result);
按来源统计代码
//-----By Source------// articles.forEach((a) => { if (!sources.has(a.source)) sources.set(a.source, { tags: new Map(), countries: new Map() }); a.tags.forEach((b) => { sources.get(a.source).tags.set(b, (sources.get(a.source).tags.get(b) ?? 0) + 1); }); a.countries.forEach((c) => { sources.get(a.source).countries.set(c, (sources.get(a.source).countries.get(c) ?? 0) + 1); }); }); const result2 = Array.from(sources) .map(([source, { tags, countries }]) => ({ source, tags: Array.from(tags).map(([tags, count]) => ({ tags, count })), countries: Array.from(countries).map(([country, count]) => ({ country, count })), })); console.log(result2);
解决方案
要实现按标签数字顺序排序,只需在将Map转换为数组后添加sort方法,把标签字符串转为数字进行比较;同时修正现有代码中与期望输出不一致的字段名:
修改后的按标签统计代码
//-----By Tag------// const tags = new Map(); // 声明变量避免全局污染 articles.forEach((a) => { a.tags.forEach((tag) => { if (!tags.has(tag)) tags.set(tag, { sources: new Map(), countries: new Map() }); tags.get(tag).sources.set(a.source, (tags.get(tag).sources.get(a.source) ?? 0) + 1); a.countries.forEach((c) => { tags.get(tag).countries.set(c, (tags.get(tag).countries.get(c) ?? 0) + 1); }); }); }); const result = Array.from(tags) // 新增排序逻辑:将标签转为数字比较大小 .sort(([tagA], [tagB]) => Number(tagA) - Number(tagB)) .map(([tag, { sources, countries }]) => ({ tag, sources: Array.from(sources).map(([source, count]) => ({ source, count })), countries: Array.from(countries).map(([country, count]) => ({ country, count })), })); console.log(result);
修改后的按来源统计代码(匹配期望输出格式+可选排序)
//-----By Source------// const sources = new Map(); // 声明变量避免全局污染 articles.forEach((a) => { if (!sources.has(a.source)) sources.set(a.source, { tags: new Map(), countries: new Map() }); a.tags.forEach((tag) => { sources.get(a.source).tags.set(tag, (sources.get(a.source).tags.get(tag) ?? 0) + 1); }); a.countries.forEach((country) => { sources.get(a.source).countries.set(country, (sources.get(a.source).countries.get(country) ?? 0) + 1); }); }); const result2 = Array.from(sources) // 可选:按来源名称排序 .sort(([sourceA], [sourceB]) => sourceA.localeCompare(sourceB)) .map(([source, { tags, countries }]) => ({ source, // 修正字段名为code,同时按标签数字排序 tags: Array.from(tags) .sort(([tagA], [tagB]) => Number(tagA) - Number(tagB)) .map(([tag, count]) => ({ code: tag, count })), // 修正字段名为code countries: Array.from(countries).map(([country, count]) => ({ code: country, count })) })); console.log(result2);
内容的提问来源于stack exchange,提问作者Eric Smith
相关产品推荐
相关产品推荐

