C# List<List<string>>使用LINQ Any方法判断重复结果异常
List<T>属于引用类型,你代码中abc == LijstVertex的判断默认走引用相等比较规则,只会检查两个变量是否指向内存中的同一个List实例,不会逐个对比列表内存储的元素值。
哪怕两个List里按顺序存的坐标字符串完全一致,只要是分别通过new List<string>()创建的不同实例,==判断都会返回false,最终导致重复校验逻辑完全失效,重复的轮廓数据被错误加入结果集。
你之前提到直接使用坐标点类型做判断同样无法得到正确结果,本质原因完全一致:如果没有为自定义坐标点类型重写相等比较逻辑,默认也是做引用地址比对,不会自动对比X、Y属性值,自然无法正确识别重复坐标。
不需要重构整体逻辑,也不需要改用Distinct编写复杂的自定义比较器,只需要把判断条件里的引用相等比较,替换为按顺序逐元素比对集合内容的SequenceEqual方法即可,完全保留你原本简单的重复项拦截思路,改动量极小:
// 替换原有的失效判断行即可 if(!GefilterdeSparingen.Any(abc => abc.SequenceEqual(LijstVertex)))
SequenceEqual会按顺序遍历两个集合的每一个元素,逐一比对值是否相等,只要两个坐标列表的点顺序、点内容完全一致,就会判定为匹配,刚好满足你的重复拦截需求。
注意:使用SequenceEqual需要确保代码文件已经引入System.Linq命名空间,一般C#项目默认会全局引入该命名空间,如果编译提示找不到方法,手动在代码文件头部加一行using System.Linq;即可。
如果待处理的数据量较大,每次调用Any+SequenceEqual都会线性遍历已存集合做全量比对,性能较差。你可以额外维护一个HashSet<string>存储已添加轮廓的唯一标识:把每个轮廓的所有坐标字符串用不会和坐标内容冲突的特殊分隔符(比如|)拼接成一个单字符串存入HashSet,后续判断重复时直接调用HashSet的Contains方法即可,时间复杂度为O(1),判断效率会高很多。如果数据量较小,直接用上面的SequenceEqual写法就足够,不需要做额外调整。
内容的提问来源于stack exchange,提问作者user12532427

