Linq 高级分组 + 计数到新模型
Posted
技术标签:
【中文标题】Linq 高级分组 + 计数到新模型【英文标题】:Linq Advanced Grouping + Count to new model 【发布时间】:2020-11-16 18:05:54 【问题描述】:我正在尝试编写一个 linq 操作来获取具有分组模型信息的唯一日期列表
到目前为止,我已经构建了这个查询,但我一直无法获得正确的输出
var result = LogModels
.Where(x => x.LogType.ToLower() == "error" &&
x.LogLevel.ToLower() == "error")
.GroupBy(inf => inf.ErrorCode)
.Select(inf => Tuple.Create(inf.Key, inf.Count()))
.ToList();
我想要得到的输出是这样的
占位符:26/07/2020 [第 1 项] ->>> 错误 = A00.1 ->>> 消息 = 设置未正确执行 ->>> 错误数量 = 2 [第 2 项] ->>> 错误 = A05.1 ->>> 消息 = 安装程序已正确安装 ->>> 错误数量 = 1
占位符:27/07/2020 [第 1 项] ->>> 错误 = A00.1 ->>> 消息 = 设置未正确执行 ->>> 错误数量 = 1 [第 2 项] ->>> 错误 = A05.1 ->>> 消息 = 安装程序已正确安装 ->>> 错误数量 = 1
我的模型类
public class LogModels
public DateTime Date get; set;
public string ErrorCode get; set;
public string Message get; set;
public string LogLevel get; set;
public string LogType get; set;
希望任何人都可以帮助我。 问候我
【问题讨论】:
为什么不按Date
而不是ErrorCode
分组? .GroupBy(inf => inf.Date.Date)
我只想获取一个包含唯一模型的日期列表,其中显示错误发生的总数并将错误消息添加到其中。
【参考方案1】:
我只想获取一个包含唯一模型的日期列表,其中显示错误发生的总数并将错误消息添加到其中
因此,您希望创建具有相同日期的错误 LogModel 组,并从每个组中计算具有相同 ErrorCode 的错误数。
显然每个错误代码都只有一个消息。没有相同 ErrorCode 和不同消息的组合:所以不是:[ErrorCode X, Message 1] [ErrorCode X, Message 2]
好吧,让我们使用overload of GroupBy that has a parameter ResultSelector: 我们会将您的 LogModel 分组到具有相同日期的组中,并使用相同的错误代码对它们进行分组:
var result = LogModels.Where(...).GroupBy(
// parameter keySelector: make groups with same Date:
logModel => logModel.Date,
// parameter resultSelector: from every found date, and all LogModels with this date make
// make one new object:
(date, logModelsWithThisDate) => new
PlaceHolder = date,
// sub-group by ErrorCode:
LogModels = logModelsWithThisDate.GroupBy(logModel => logModel.ErrorCode,
// parameter resultSelector: from the errorCode,
// and all logModels with this errorCode make one new:
(errorCode, logModelsWithThisErrorCode) => new
Error = errorCode,
// you know that all logModels with this ErrorCode have the same Message,
// so you can take any LogModel to get the Message:
Message = logModelsWithThisErrorCode
.Select(logModel => logModel.Message)
.FirstOrDefault(),
ErrorQty = logModelsWithThisErrorCode.Count(),
),
);
或者,您可以对 ErrorCode 和 Message 进行分组
.GroupBy(logModel => new
ErrorCode = logModel.ErrorCode,
Message = logModel.Message,
,
// ResultSelector:
(error, logModelsWithThisError) => new
ErrorCode = error.ErrorCode,
Message = error.Message,
ErrorQty = logModelsWithThisError.Count(),
)
虽然这样可行,而且结果选择器看起来更好,但效率较低,因为对于每个键,它必须同时检查 ErrorCode 和 Message,而您确实知道如果 x.ErrorCode 等于 y.ErrorCode,那么x.Message 将等于 y.Message,那么为什么要检查呢?
【讨论】:
感谢您的帮助。没有你就不会找到它!有什么关于 Linq 的好书推荐吗? 考虑The Standard Linq Operators。要了解 LINQ 背后的工作原理:Extension methods demystified。如果您忘记了适合您需要的方法,这也有助于您创建新的 LINQ 方法。有时,foreach (...)
和 yield return
比一个大而复杂的 LINQ 语句更容易理解以上是关于Linq 高级分组 + 计数到新模型的主要内容,如果未能解决你的问题,请参考以下文章