如何筛选List<>中不在指定字符串内的元素?
问题分析
原代码存在两个核心问题:
- 遍历集合时直接删除元素导致索引异常:正向
for循环中删除元素后,后续元素会自动前移,索引i递增会跳过下一个元素,出现漏判。 - 字符串包含判断逻辑错误:直接用
FilterStr.Contains(属性值)会出现误匹配,比如属性值是"B"时,"NB|JA".Contains("B")会返回true,不符合精确匹配筛选值的需求。
解决方案
核心思路
先把|分隔的筛选字符串拆分为精确匹配的集合,再通过安全的方式筛选/删除元素,同时优化反射操作提升性能。
方案1:LINQ筛选(推荐,返回新集合)
这种方式不修改原集合,直接生成符合要求的新集合,逻辑清晰且避免索引问题:
// 拆分筛选字符串为HashSet,提升精确匹配的效率 var filterSet = new HashSet<string>(filterstr.Split('|', StringSplitOptions.RemoveEmptyEntries)); // 提前获取目标属性的反射信息,避免循环中重复反射 var targetProperty = typeof(DoorDetails).GetProperty(FilterOrder); if (targetProperty == null) { // 处理属性不存在的异常情况,比如返回空集合或抛出自定义异常 return new List<DoorDetails>(); } // 筛选属性值不在筛选集合中的元素 var filteredList = ListDoorData.Where(door => { var propertyValue = targetProperty.GetValue(door)?.ToString(); return !filterSet.Contains(propertyValue); }).ToList();
方案2:直接修改原集合(反向遍历删除)
如果需要直接修改原ListDoorData,采用反向遍历避免索引错乱:
var filterSet = new HashSet<string>(filterstr.Split('|', StringSplitOptions.RemoveEmptyEntries)); var targetProperty = typeof(DoorDetails).GetProperty(FilterOrder); if (targetProperty == null) return; // 反向遍历,删除元素不会影响未遍历的索引 for (int i = ListDoorData.Count - 1; i >= 0; i--) { var propertyValue = targetProperty.GetValue(ListDoorData[i])?.ToString(); if (filterSet.Contains(propertyValue)) { ListDoorData.RemoveAt(i); } }
方案3:批量删除(先收集待删元素)
另一种安全修改原集合的方式,先收集所有需要删除的元素,再批量移除:
var filterSet = new HashSet<string>(filterstr.Split('|', StringSplitOptions.RemoveEmptyEntries)); var targetProperty = typeof(DoorDetails).GetProperty(FilterOrder); if (targetProperty == null) return; // 收集所有需要删除的元素 var itemsToRemove = ListDoorData.Where(door => { var propertyValue = targetProperty.GetValue(door)?.ToString(); return filterSet.Contains(propertyValue); }).ToList(); // 批量移除 foreach (var item in itemsToRemove) { ListDoorData.Remove(item); }
关键优化点说明
- HashSet的使用:相比
List,HashSet的Contains方法时间复杂度为O(1),当筛选值较多时性能优势明显。 - 反射优化:提前获取
PropertyInfo,避免每次循环都重复调用GetType().GetProperty,减少性能损耗。 - 空值处理:用
?.ToString()处理属性值为null的情况,避免空引用异常。
内容的提问来源于stack exchange,提问作者KitKat
相关产品推荐
相关产品推荐

