C#高效筛选同类型列表:基于y2坐标差值条件
高效筛选符合y2差值条件的列表元素
针对你需要保留TSOCoord和ITEMCoord2中与CheckCoord元素y2差值小于10的条目的需求,三层foreach循环的时间复杂度会随着数据量增大急剧上升(O(MN + KN),M、K、N分别是三个列表的长度),下面是两种更高效的实现方案:
方案一:基于排序+二分查找的快速匹配
先提取CheckCoord的y2值并排序,之后用二分查找快速定位可能符合条件的范围,避免全量遍历:
// 预处理:提取CheckCoord的y2值并排序 var sortedCheckY2 = checkCoords.Select(c => c.y2).OrderBy(y => y).ToList(); // 辅助方法:判断目标y2是否存在匹配的Check元素 private bool HasMatchingY2(int targetY, List<int> sortedYValues) { // 用二分查找找到第一个大于等于 targetY - 10 的元素索引 int searchIndex = sortedYValues.BinarySearch(targetY - 10); searchIndex = searchIndex < 0 ? ~searchIndex : searchIndex; // 从该索引开始遍历,直到元素超出 targetY + 10 的范围 for (int i = searchIndex; i < sortedYValues.Count; i++) { int currentY = sortedYValues[i]; if (currentY > targetY + 10) break; if (Math.Abs(currentY - targetY) < 10) return true; } return false; } // 筛选目标列表 var filteredTSOCoord = TSOCoord.Where(t => HasMatchingY2(t.y2, sortedCheckY2)).ToList(); var filteredITEMCoord2 = ITEMCoord2.Where(i => HasMatchingY2(i.y2, sortedCheckY2)).ToList();
方案二:区间合并优化(适合CheckCoord存在大量相近y2值的场景)
先将CheckCoord每个元素的y2转换为有效匹配区间([y2-10, y2+10]),合并重叠/相邻的区间后,用二分查找判断目标y2是否落在任何区间内:
// 预处理:生成CheckCoord对应的匹配区间并排序 var checkIntervals = checkCoords .Select(c => (Start: c.y2 - 10, End: c.y2 + 10)) .OrderBy(iv => iv.Start) .ToList(); // 合并重叠/相邻的区间 var mergedIntervals = new List<(int Start, int End)>(); foreach (var interval in checkIntervals) { if (mergedIntervals.Count == 0) { mergedIntervals.Add(interval); continue; } var lastInterval = mergedIntervals.Last(); if (interval.Start <= lastInterval.End) { // 区间重叠或相邻,合并为更大的区间 mergedIntervals.RemoveAt(mergedIntervals.Count - 1); mergedIntervals.Add((lastInterval.Start, Math.Max(lastInterval.End, interval.End))); } else { mergedIntervals.Add(interval); } } // 辅助方法:判断目标y2是否落在合并后的区间内 private bool IsY2InMatchingRange(int targetY, List<(int Start, int End)> intervals) { int left = 0, right = intervals.Count - 1; while (left <= right) { int mid = (left + right) / 2; var currentInterval = intervals[mid]; if (targetY < currentInterval.Start) right = mid - 1; else if (targetY > currentInterval.End) left = mid + 1; else return true; } return false; } // 筛选目标列表 var filteredTSOCoord = TSOCoord.Where(t => IsY2InMatchingRange(t.y2, mergedIntervals)).ToList(); var filteredITEMCoord2 = ITEMCoord2.Where(i => IsY2InMatchingRange(i.y2, mergedIntervals)).ToList();
效率说明
两种方案的预处理阶段时间复杂度为O(N log N)(排序/区间合并),筛选阶段为O(M log N + K log N),相比三层循环的O(MN + KN),在数据量较大时性能提升非常明显。
内容的提问来源于stack exchange,提问作者tahirhasan
相关产品推荐
相关产品推荐

