如何简化C#不同对象列表的匹配移除逻辑?List.Except()不可用
优化方案
首先,你原来的嵌套foreach写法存在潜在问题:直接在遍历ImagesByPerimeterId的同时调用Remove,会抛出InvalidOperationException——枚举集合时不允许修改集合本身。你说运行正常,大概率是实际代码里隐式加了.ToList()创建了遍历副本,但就算能跑,这种O(n*m)的嵌套循环在列表元素较多时效率极低。
给你两种更简洁高效的实现方式:
方法一:用RemoveAll直接修改原列表
先把要排除的ImageId提取到HashSet中(HashSet的查找是O(1),远快于List的O(n)),再调用RemoveAll批量移除匹配元素:
// 提取所有需要排除的ImageId,用HashSet提升查找效率 var excludedIds = new HashSet<int>(ImagesWithMorePerimeters.Select(tile => tile.ImageId)); // 批量移除匹配的元素 ImagesByPerimeterId.RemoveAll(img => excludedIds.Contains(img.Id));
方法二:生成新列表替换原列表
如果允许替换原列表变量,用LINQ的Where筛选出无需移除的元素,再转成List:
var excludedIds = new HashSet<int>(ImagesWithMorePerimeters.Select(tile => tile.ImageId)); ImagesByPerimeterId = ImagesByPerimeterId.Where(img => !excludedIds.Contains(img.Id)).ToList();
至于你尝试的Except方法,它要求两个集合的元素类型相同,或者需要自定义相等比较器,相比上面的方案反而更繁琐,所以不推荐。
内容的提问来源于stack exchange,提问作者Lucas Zanon
相关产品推荐
相关产品推荐

