如何统计按姓名日期排序数组中三月内出现≥3次的同名数量?
统计满足「三个月内出现至少3次」的姓名数量
输入的待处理数组(按姓名、日期排序,日期格式为dd/mm/yyyy):
[ {name: "A", date: "1/1/2022"}, {name: "A", date: "2/1/2022"}, {name: "A", date: "13/1/2022"}, {name: "B", date: "1/3/2022"}, {name: "B", date: "3/7/2022"}, {name: "B", date: "6/12/2022"}, {name: "C", date: "11/1/2022"}, {name: "C", date: "1/5/2022"}, {name: "C", date: "1/6/2022"}, {name: "C", date: "1/7/2022"} ]
需求与规则
需要统计其中满足三个月内出现至少3次的姓名数量,规则如下:
- 只要该姓名的任意一组记录中,存在至少3条记录的时间范围不超过3个月,即计入统计
- 一旦确认某姓名符合条件,可直接跳过该姓名的后续条目,无需继续检查
示例说明
- A的3条记录都在1月内,符合条件,计入统计
- B的三条记录间隔均超过3个月,不符合
- C的第2、3、4条记录(5月1日、6月1日、7月1日)在3个月内,符合条件,计入统计
最终预期返回结果:2
解决方案与代码实现
思路步骤
- 日期转换:将字符串日期转为可计算的时间戳,注意处理
dd/mm/yyyy格式的月份索引(JS中Date对象月份从0开始) - 分组检查:按姓名分组遍历记录,用滑动窗口逻辑检查是否存在符合条件的3条记录
- 提前终止:一旦某姓名符合条件,立即停止检查该姓名的后续记录
- 统计结果:最终统计符合条件的姓名总数
JavaScript代码实现
function countQualifiedNames(arr) { // 转换dd/mm/yyyy格式日期为时间戳 const parseDate = (dateStr) => { const [day, month, year] = dateStr.split('/').map(Number); return new Date(year, month - 1, day).getTime(); }; const threeMonthsMs = 90 * 24 * 60 * 60 * 1000; // 按90天近似3个月 const qualifiedNames = new Set(); let currentName = null; let currentTimestamps = []; for (const item of arr) { if (item.name !== currentName) { // 处理上一个姓名的剩余记录 if (currentName && !qualifiedNames.has(currentName)) { for (let i = 0; i < currentTimestamps.length - 2; i++) { if (currentTimestamps[i + 2] - currentTimestamps[i] <= threeMonthsMs) { qualifiedNames.add(currentName); break; } } } // 重置当前姓名和时间戳列表 currentName = item.name; currentTimestamps = [parseDate(item.date)]; } else { const timestamp = parseDate(item.date); currentTimestamps.push(timestamp); // 记录数达标时提前检查,符合条件则标记并跳过后续记录 if (currentTimestamps.length >= 3 && !qualifiedNames.has(currentName)) { const earliest = currentTimestamps[currentTimestamps.length - 3]; if (timestamp - earliest <= threeMonthsMs) { qualifiedNames.add(currentName); currentTimestamps = []; // 清空列表,跳过后续该姓名的条目 } } } } // 处理最后一个姓名的记录 if (currentName && !qualifiedNames.has(currentName)) { for (let i = 0; i < currentTimestamps.length - 2; i++) { if (currentTimestamps[i + 2] - currentTimestamps[i] <= threeMonthsMs) { qualifiedNames.add(currentName); break; } } } return qualifiedNames.size; } // 测试输入 const input = [ {name: "A", date: "1/1/2022"}, {name: "A", date: "2/1/2022"}, {name: "A", date: "13/1/2022"}, {name: "B", date: "1/3/2022"}, {name: "B", date: "3/7/2022"}, {name: "B", date: "6/12/2022"}, {name: "C", date: "11/1/2022"}, {name: "C", date: "1/5/2022"}, {name: "C", date: "1/6/2022"}, {name: "C", date: "1/7/2022"} ]; console.log(countQualifiedNames(input)); // 输出:2
内容的提问来源于stack exchange,提问作者helloworldbyeworld
相关产品推荐
相关产品推荐

