如何检测单账户任意7天滚动周期内的催收呼叫违规情况
滚动7天周期内呼叫违规检测方案
核心思路
因为需要覆盖任意连续7天的滚动周期,固定周分组的方法无法满足需求,必须对每个账户的呼叫记录按时间排序后,用双指针滑动窗口的方式统计每个时间点对应的7天窗口内的呼叫次数,判断是否超过7次。
具体实现步骤
按账户分组并排序
先将筛选后的呼叫记录按账户分组,每组内按呼叫时间升序排列,确保后续滑动窗口的逻辑可以正确执行:var groupedCalls = calls.GroupBy(c => c.AccountNumber) .ToDictionary(g => g.Key, g => g.OrderBy(c => c.CallDate).ToList());双指针滑动窗口检测违规
遍历每个账户的呼叫列表,用左右指针维护一个"7天内"的窗口:- 右指针逐个遍历呼叫记录,计算当前呼叫时间往前推7天的边界
- 左指针不断右移,直到指向的呼叫时间不早于这个7天边界
- 此时窗口内的呼叫次数即为右指针减左指针加1,若超过7次则记录违规
var violations = new List<(string AccountNumber, DateTime WindowStart, DateTime WindowEnd, int CallCount)>(); foreach (var accountGroup in groupedCalls) { var accountCalls = accountGroup.Value; int left = 0; for (int right = 0; right < accountCalls.Count; right++) { // 计算当前呼叫对应的7天前的时间边界 var sevenDaysAgo = accountCalls[right].CallDate.AddDays(-7); // 移动左指针,确保窗口内所有呼叫都在7天范围内 while (accountCalls[left].CallDate < sevenDaysAgo) { left++; } int currentCallCount = right - left + 1; if (currentCallCount > 7) { // 记录违规信息:账户、窗口起止时间、呼叫次数 violations.Add(( accountGroup.Key, accountCalls[left].CallDate, accountCalls[right].CallDate, currentCallCount )); } } }违规记录去重(可选)
同一违规窗口可能会被多次触发(比如第8、9次呼叫都会触发违规),可以按账户和窗口起始时间去重,保留每条违规的首次记录:var distinctViolations = violations .GroupBy(v => new { v.AccountNumber, v.WindowStart }) .Select(g => g.First()) .ToList();
适配不同的"7天"定义
如果法规中的"7天"指自然日周期(而非精确的7×24小时),可以将CallDate转换为日期部分再计算边界:
var sevenDaysAgoDate = accountCalls[right].CallDate.Date.AddDays(-7); while (accountCalls[left].CallDate.Date < sevenDaysAgoDate) { left++; }
内容的提问来源于stack exchange,提问作者JDSchenck
相关产品推荐
相关产品推荐

