尝试将Distinct()放入一个相对复杂的LINQ查询中
本文关键字:复杂 相对 LINQ 一个 查询 Distinct | 更新日期: 2023-09-27 17:52:42
到目前为止,我有这个查询:
var msg = ModelState.Values
.Where(x => x.Errors.Any())
.Select(c => c.Errors.Select(d => d.ErrorMessage).Aggregate((e, f) => (e ?? "") + "<br/>" + f))
.Aggregate((x, y) => (x ?? "") + "<br/>" + y);
这是完美的工作,但我需要过滤掉重复的错误消息。我尝试将GroupBy()和Distinct()添加到获取ErrorMessage的谓词之前和之后的几个地方。我错过了什么?
如果我按原样运行,我将收到以下结果:
"Contact Email address invalid<br/>Contact Email address invalid"
这里的每个ErrorMessage值都是"Contact Email address invalid"。这些是我想要过滤掉的重复内容。
我可以建议一个替代方案吗?
假设您想要不同的消息,由break标签分隔:
var items = ModelState.Values
.SelectMany(c => c.Errors.Select(d => d.ErrorMessage))
.Distinct()
.ToArray();
string msg = string.Join("<br/>", items);
问题是您有两个地方产生值。考虑以下情况:
Value Errors
1. "Bad username", "Contact Email address invalid"
2. "Contact Email address invalid"
即使您将Distinct
添加到两个Select
调用中,它也不会做您想要的,因为Bad username<br/>Contact Email address invalid
将与Contact Email address invalid
进行比较,将发现不相等,并将聚合到Bad username<br/>Contact Email address invalid<br/>Contact Email address invalid
中,我认为这不是您想要的。
相反,您应该首先平坦化嵌套的错误列表。这是SelectMany
的工作。要使列表平整化,你只需要这样做:
var errorMessages = ModelState.Values
.Where(x => x.Errors.Any())
.SelectMany(c => c.Errors.Select(d => d.ErrorMessage))
现在errorMessages
是来自每个Value
的每个错误消息的列表。(注意Where
可能不需要: Select
或SelectMany
在空序列上是no-op。)
现在是第二个问题:
由于string
的不可变性,在c#中对字符串使用+
几乎总是不好的做法。相反,您希望使用string.Join
、string.Format
或StringBuilder
,这取决于您的输入是一个序列、多个变量还是更长的字符串。在本例中,您有一个数组,因此string.Join
是选择的工具:
var msg = string.Join("<br/>", errorMessages.Distinct())