C#中优化相邻日期范围合并逻辑的性能问题
C#中优化相邻日期范围合并逻辑的性能问题
嗨,我来帮你捋捋这个日期范围合并的性能优化问题~
首先得说说你现有代码的几个问题,这也是导致它慢甚至可能出错的原因:
- 直接在原列表上修改,还继续用初始的
count值循环,会导致重复处理已经合并过的元素;而且当i走到最后一个元素时,i+1会直接越界报错! - 计算时间差的方式太绕了:
TimeSpan.ToString()根本不是返回天数数字,你这么转int完全是错的,还额外增加了不必要的字符串操作,拖慢性能。
那怎么优化呢?其实咱们可以换个思路:创建一个新列表来存储合并后的结果,只遍历原列表一次,这样时间复杂度是O(n),效率会高很多,逻辑也更清晰。
具体步骤和代码是这样的:
- 先确保原列表是按
StartDate排序的(如果没排序的话,合并逻辑会乱哦),然后初始化一个新的结果列表。 - 把第一个日期范围加入结果列表作为初始值。
- 从第二个元素开始遍历原列表,每次拿当前元素和结果列表的最后一个元素比较:
- 如果当前范围的
StartDate比上一个范围的EndDate刚好大1天,就合并(更新上一个范围的EndDate为当前的EndDate) - 否则就把当前范围直接加入结果列表
- 如果当前范围的
代码示例:
// 先确保列表是按StartDate排序的(如果你的数据没提前排序的话) var sortedDatas = datas.OrderBy(r => r.StartDate).ToList(); var mergedRanges = new List<YourViewModelType>(); if (sortedDatas == null || !sortedDatas.Any()) return mergedRanges; // 加入第一个范围作为初始项 mergedRanges.Add(sortedDatas[0]); for (int i = 1; i < sortedDatas.Count; i++) { var lastMergedRange = mergedRanges.Last(); // 计算两个日期的天数差(用Date属性避免时间部分干扰) int dayDifference = sortedDatas[i].StartDate.Date.Subtract(lastMergedRange.EndDate.Date).Days; if (dayDifference == 1) { // 合并:更新最后一个范围的结束日期 lastMergedRange.EndDate = sortedDatas[i].EndDate; } else { // 无法合并,添加新的范围 mergedRanges.Add(sortedDatas[i]); } }
为啥这个方法更快?因为咱们只需要遍历原列表一次,没有多余的重复操作,也避免了原代码里的索引越界问题。而且计算天数差直接用TimeSpan.Days属性,不用绕字符串转换,性能自然就上去了。
举个例子,用你给的测试数据:
2024/03/21-2024/03/22
2024/03/23-2024/03/25
2024/03/26-2024/03/28
2024/04/01-2024/04/02
这个代码会先把第一个范围加入结果,然后第二个范围的StartDate(2024/03/23)和第一个的EndDate(2024/03/22)差1天,就合并成2024/03/21-2024/03/25;接着第三个范围的StartDate(2024/03/26)和合并后的EndDate(2024/03/25)差1天,继续合并成2024/03/21-2024/03/28;最后第四个范围和前面的差了好几天,就直接加入结果,完美得到你想要的输出~
备注:内容来源于stack exchange,提问作者Sara tabaghchi
相关产品推荐
相关产品推荐

