C# Linq从类对象列表获取不在字符串列表内首个匹配值的实现方法
正确实现方式
你原有写法存在两个核心错误:
- 调用逻辑写反:
string.Contains()的参数是待匹配的子字符串,你传入整个HashSet集合属于类型不匹配;判断值是否在HashSet中应该调用HashSet自身的Contains()方法,查询效率为O(1)。 - 没有处理嵌套集合结构:外层是响应对象列表,每个响应对象内部嵌套了Header列表,你需要先把嵌套的列表打平为单层序列,再做筛选取首项。
完全匹配场景(ResultMessage与matches中的值完全相等才判定为命中)
如果需求是ResultMessage的值完全等于matches集合中的任意值就跳过,取第一个不满足该条件的项,使用以下代码:
// 取第一个不符合项的ResultMessage值,无匹配时返回null var returnMessage = result .SelectMany(resp => resp.Header) // 将所有响应下的Header列表合并为单层的SalesOrderDto序列 .FirstOrDefault(dto => !matches.Contains(dto.ResultMessage))? .ResultMessage;
如果需要获取整个匹配的SalesOrderDto对象而非仅ResultMessage值,去掉末尾的.ResultMessage即可。
对应的查询表达式写法:
var returnMessage = ( from resp in result from dto in resp.Header // 双重from等价于SelectMany的打平逻辑 where !matches.Contains(dto.ResultMessage) select dto.ResultMessage ).FirstOrDefault();
模糊匹配场景(ResultMessage包含matches中的任意文本就算命中)
如果你的需求是只要ResultMessage包含matches里的任意片段就算命中,而非完全值相等,改用以下写法:
var returnMessage = result .SelectMany(resp => resp.Header) .FirstOrDefault(dto => !matches.Any(matchText => dto.ResultMessage.Contains(matchText)))? .ResultMessage;
说明:代码中末尾的
?是C# 6及以上版本支持的空条件运算符,用于避免无匹配项时FirstOrDefault返回null触发空引用异常;如果使用旧版本C#,请先判断FirstOrDefault返回的对象是否为null,再读取ResultMessage属性。
内容的提问来源于stack exchange,提问作者Rowan
相关产品推荐
相关产品推荐

