public class job
{
public int Id { get; set; }
public string JobNumber { get; set; }
public bool IsValid { get; set; }
}
public class attachment
{
public string JobNumber { get; set; }
public int id { get; set; }
}
List<job> joblist = new List<job>();
List<attachment> attachments = new List<attachment>();
for (int i = 0; i < joblist.Count; i++)
{
for (int j = 0; j < attachments.Count; j++)
{
if(joblist[i].JobNumber == attachments[j].JobNumber)
{
joblist[i].IsValid = true;
}
}
}
如果作业列表类和附件列表类都具有相同的作业号,我们将其设为有效 有什么办法可以使用linq来改进此代码
答案 0 :(得分:2)
使用Any
查找具有相应JobNumber
的附件:
foreach (var j in joblist)
{
j.IsValid = attachments.Any(a => a.JobNumber == j.JobNumber);
}
请记住,这仍然是(最坏的情况) O(n²)操作,尽管平均而言它的效率比原始代码要高一些,因为查找后循环没有break
一场比赛。
答案 1 :(得分:1)
使用HashSet
,可以优化附件为O(1)的测试,但是创建HashSet
的开销只有在列表很长的情况下才值得附件或很长的工作列表,或者将相同的附件列表与许多不同的工作列表一起使用:
var HasAttachment = attachments.Select(a => a.JobNumber).ToHashSet();
for (int i = 0; i < joblist.Count; i++) {
joblist[i].IsValid = HasAttachment.Contains(joblist[i].JobNumber);
}
答案 2 :(得分:0)
这不是纯粹的LINQ,但是您可以对内部循环的joblist.Count
枚举进行交易,并为attachments
的一个枚举完全删除它。
HashSet<string> attachmentJobNumbers = new HashSet<string>(
// A one-time enumeration of attachments to collect its JobNumber values
attachments.Select(attachment => attachment.JobNumber)
);
for (int i = 0; i < joblist.Count; i++)
{
joblist[i].IsValid = attachmentJobNumbers.Contains(joblist[i].JobNumber);
}
HashSet<>
允许快速查找特定JobNumber
是否存在任何附件。假定没有等效的JobNumber
值仅因大小写而有所不同。否则,您可以将StringComparer
传递给HashSet<>
构造函数的重载...
HashSet<string> attachmentJobNumbers = new HashSet<string>(
// A one-time enumeration of attachments to collect its JobNumber values
attachments.Select(attachment => attachment.JobNumber),
StringComparer.OrdinalIgnoreCase
);
...获得不区分大小写的查询。
(从@NetMage's answer中我了解到ToHashSet()
extension method自.NET 4.7.2 / .NET Core 2.0以来就存在了,因此这是一种方便的选择。)
使用ToDictionary()
...做纯净的LINQ方式做同样的事情...
// A one-time enumeration of attachments to collect its JobNumber values
Dictionary<string, attachment> attachmentsByJobNumber = attachments.ToDictionary(attachment => attachment.JobNumber);
for (int i = 0; i < joblist.Count; i++)
{
joblist[i].IsValid = attachmentsByJobNumber.ContainsKey(joblist[i].JobNumber);
}
...或ToLookup()
,尽管在不需要attachment
的情况下,也可以通过JobNumber
来获得attachment
,而只需{{1 }}对“ bool
是否有附件?”的答案。我认为JobNumber
可以更好地代表此用例。
此外,请记住,.NET的naming guidelines要求types和properties使用Pascal大小写,因此您应该使用HashSet<>
,Job
,和Attachment
(或者可能是Id
)。