我有一个for循环来获取非常耗时的数据。有人建议将其转换为linq。提前谢谢。
iListReport = obj.GetClosedReports();
string sRepType ="";
foreach (ReportStatisticsInfo item in reportStatistic)
{
sRepType = item.ReportName.Trim();
IList<string> lastClosedReport = new List<string>();
foreach (TaskListInfo taskInfo in iListReport)
{
string reportName = taskInfo.DocumentName.Trim();
if (string.Compare(sRepType, reportName, true) == 0)
{
if (taskInfo.ActionID == Convert.ToInt16(ReportAction.Close) && !lastClosedReport.Contains(taskInfo.DocumentID))
{
iClosedreportCount += 1;
lastClosedReport.Add(taskInfo.DocumentID);
}
}
}
}
答案 0 :(得分:1)
使用LINQ,您将获得一个带有重复项的IEnumerable<string>
from item in reportStatistic
from taskInfo in iiListReport
where (string.Compare(item.ReportName.Trim(), taskInfo.DocumentName.Trim(), true) == 0)
&& taskInfo.ActionID == Convert.ToInt16(ReportAction.Close)
select taskInfo.DocumentID
然后您可以Distinct().GroupBy(d => d.taskInfo)
答案 1 :(得分:1)
你走了。我已经将您的代码完全翻译成LINQ,希望能帮助您了解我是如何转换它的。
请注意使用let
关键字,它允许您声明范围变量(允许您执行一次修剪,然后在多个位置使用结果)。
另请注意在LINQ查询底部使用group by
以确保我们只接受每个documentID的第一次出现。
IList iListReport = obj.GetClosedReports();
var query = from item in reportStatistic
let sRepType = item.ReportName.Trim()
from taskInfo in iListReport
let reportName = taskInfo.DocumentName.Trim()
where string.Compare(sRepType, reportName, true) == 0
&& taskInfo.ActionID == Convert.ToInt16(ReportAction.Close)
//here's how we make sure we don't get the same documentID twice
//we group by the id and then take the first
group taskInfo by taskInfo.DocumentID into grouping
select grouping.First().DocumentID;
var lastClosedReport = query.ToList();
iClosedreportCount = lastClosedReport.Count;
以下是您的代码与LINQ版本的一些比较,以帮助您,如果您有时需要再次进行转换。希望这将有助于那些必须将foreach循环转换为LINQ的其他人。
您可以为LINQ from子句执行foreach子句的直接交换。你可以看到这个:
foreach (ReportStatisticsInfo item in reportStatistic)
已成为:
from item in reportStatistic
在foreach中声明变量时,可以将它们换成LINQ let语句。你可以看到这个声明:
sRepType = item.ReportName.Trim();
已成为:
let sRepType = item.ReportName.Trim()
你的if语句可以在where子句中。您可以看到以下两个if语句:
if (string.Compare(sRepType, reportName, true) == 0)
if (taskInfo.ActionID == Convert.ToInt16(ReportAction.Close)
已经成为这个where子句
where string.Compare(sRepType, reportName, true) == 0
&& taskInfo.ActionID == Convert.ToInt16(ReportAction.Close)
到目前为止,这一切都非常简单,因为一切都是直接交换。最棘手的部分是您可以防止重复项出现在结果列表中的代码。
if (taskInfo.ActionID == Convert.ToInt16(ReportAction.Close)
&& !lastClosedReport.Contains(taskInfo.DocumentID))
{
iClosedreportCount += 1;
lastClosedReport.Add(taskInfo.DocumentID);
}
这很棘手,因为它是LINQ中我们必须做的唯一不同的部分。
首先,我们将'taskInfo'分组为'DocumentID'。
group taskInfo by taskInfo.DocumentID into grouping
然后我们从每个分组中获取第一个taskInfo并获取它的ID。
select grouping.First().DocumentID;
关于Distinct的说明
很多人尝试使用Distinct来摆脱重复。当我们使用原始类型时,这很好,但是当你使用一组对象时,这可能会失败。当您使用对象时,Distinct将对两个对象进行参考比较。这将无法匹配不同实例但碰巧具有相同ID的对象。
如果您需要根据对象中的特定属性删除重复项,那么最好的方法是使用group by。