我有一个FORACH,在这个FORACH中我遍历一个列表,在这个FORACH中我有一个条件来判断在另一个有20万行的列表中是否有特定的信息是字符串.

我想快点做.

  foreach(var dto in List){
    // the problem is here
    if(anotherList.Any(d => d.id == dto.id && d.line.equals(dto.line))) 
          continue;
    }

我希望能快一点.

推荐答案

Any的复杂度为O(n),其中n是集合中的元素数(anotherList),因此代码的总体复杂度为O(m*n),其中m是List中的元素数.如果id是唯一,那么您可以创建查找字典,它在一般情况下应该具有恒定的查找时间,并执行如下操作:

var dict = anotherList
  .ToDictionary(d => d.Id);

foreach(var dto in List)
{
    if (dict.TryGetValue(dto.Id, out var val) && val.line.equals(dto.line))
    {
        continue;
    }
}

这应该会将复杂性降低到O(m+n).

如果每个ID有多个字符串,则可以考虑以下选项:

  1. 如果每个ID的字符串不多,请使用Lookup<TKey,TElement>:

表示键的集合,每个键都映射到一个或多个值.

然后搜索匹配元素的集合

  1. 构建从IdHashSet<strings>的词典,并判断哈希集:
var dictOfSets = anotherList
    .GroupBy(d => d.Id)
    .ToDictionary(gr => gr.Key, gr => gr.Select(d => d.Line).ToHashSet());

foreach(var dto in List)
{
    if (dictOfSets.TryGetValue(dto.Id, out var val) && val.Contains(dto.Line))
    {
        continue;
    }
}
  1. 试着利用value tuples和它生成的GetHashcodeEquals来构建相应的哈希表(基本思想是一样的-你需要"常量"查找):
var hashSet = anotherList
    .Select(d => (d.Id, d.Line))
    .ToHashSet();

foreach(var dto in List)
{
    if (hashSet.Contains((dto.Id, dto.Line)))
    {
        continue;
    }
}

阅读更多:

Csharp相关问答推荐

Rx.Net -当关闭序列被触发时如何聚合消息并发出中间输出?

Serilog SQL服务器接收器使用UTC作为时间戳

AutoMapper -如何为两个不同的用例设置单个映射?

如何在NodaTime中为Instant添加一年?

Nuget包Serilog.Sinks.AwsCloudwatch引发TypeLoadExceptions,因为父类型是密封的

如何将MongoDB序列化程序设置为内部对象属性

如何使用自定义负载均衡器管理Ocelot负载均衡器中的多线程和批读取

NET8 Maui&;iOS:AppCenter崩溃错误

DateTime ToString()未以指定格式打印

如何管理Azure认证客户端响应和证书 fingerprint

在C#中过滤Excel文件

在使用AWS SDK for.NET时,如何判断S3是否已验证我的对象的校验和?

发布.NET 8 Blazor WebAssembly独立应用程序以进行静态站点部署

如何在使用属性 Select 器时判断是否可以为空

C#无法将.csv列转换为用于JSON转换的列表

如何在使用Google.Drive.apis.V3下载文件/文件夹之前压缩?

避免在特定区域中设置Visual Studio代码的自动格式

我可以阻止类型上的Object.ToString()吗?

.NET6最小API:操作.MapGet之后的响应

ASP.NET核心中的验证错误-该字段为必填字段