首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用list对象中的3个属性的搜索条件来加速List<>上的linq查询

如何使用list对象中的3个属性的搜索条件来加速List<>上的linq查询
EN

Stack Overflow用户
提问于 2015-02-17 18:26:33
回答 4查看 1.5K关注 0票数 3

我有以下LINQ查询。

大约有55 000件物品的清单。我需要对条目中属性的三个进行搜索。

这是我的代码:

代码语言:javascript
复制
private List<Device> Devices = _db.Devices.ToList();

public Device TryFindDeviceInNetworks(ALL_Sims sim)
{
    var ips = new List<string>();
    if (sim.IP1 != null)
    {
        ips.Add(sim.IP1);
    }
    if (sim.IP2 != null)
    {
        ips.Add(sim.IP2);
    }

    var device =
        Devices.FirstOrDefault(
            x => ips.Contains(x.IPaddress1)
                 || ips.Contains(x.IPaddress2)
                 || ips.Contains(x.IPaddress3));

    return device;
}

目前,这个操作需要一些时间。

我有一个for循环,遍历大约100 k项,在每次迭代中调用这个函数TryFindDeviceInNetworks()。它在英特尔i5上运行8-10小时。显然这是单线程的。

我的问题是我怎样才能加快速度?我已经将我的一些列表转换成字典,在应用程序中我可以这样做,这对我有很大的帮助,但是在这种情况下,我不能只搜索一个键?

是否有比List<T>更适合的数据结构?

数据库不在局域网上,因此每次迭代都会增加至少40 is +查询时间的估计ping。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2015-02-17 18:56:56

与其拥有一个包含所有3个IP地址的字典,不如使用3个字典:

代码语言:javascript
复制
private List<Device> Devices = new List<Device>();

private Dictionary<string, Device> mapIP1;
private Dictionary<string, Device> mapIP2;
private Dictionary<string, Device> mapIP3;

在执行搜索之前,您必须初始化它们:

代码语言:javascript
复制
public void InitializeDictionaries()
{
    mapIP1 = Devices.ToDictionary(x => x.IPaddress1);
    mapIP2 = Devices.ToDictionary(x => x.IPaddress2);
    mapIP3 = Devices.ToDictionary(x => x.IPaddress3);
}

搜索本身可以使用TryGetValue

代码语言:javascript
复制
public Device TryFindDeviceInNetworks(ALL_Sims sim)
{
    Device device = null;

    if (sim.IP1 != null)
    {
        if (mapIP1.TryGetValue(sim.IP1, out device))
            return device;
        if (mapIP2.TryGetValue(sim.IP1, out device))
            return device;
        if (mapIP3.TryGetValue(sim.IP1, out device))
            return device;
    }

    if (sim.IP2 != null)
    {
        if (mapIP1.TryGetValue(sim.IP2, out device))
            return device;
        if (mapIP2.TryGetValue(sim.IP2, out device))
            return device;
        if (mapIP3.TryGetValue(sim.IP2, out device))
            return device;
    }

    return device;
}

但是,您必须确保Devices列表中没有共享相同地址的元素,因为Dictionary<TKey, TValue>不能处理重复的键。

票数 3
EN

Stack Overflow用户

发布于 2015-02-17 18:37:20

代码语言:javascript
复制
var device =
    Devices.FirstOrDefault(
        x => ips.Contains(x.IPaddress1)
             || ips.Contains(x.IPaddress2)
             || ips.Contains(x.IPaddress3));

在最坏的情况下(不匹配),将枚举ips三次。我会把它改写为:

代码语言:javascript
复制
var device =
    Devices.FirstOrDefault(
        x => ips.Any(y => y == x.IPaddress1
             || y == x.IPaddress2
             || y == x.IPaddress3);

因此,它只枚举一次,检查每个可能的“匹配条件”,并在找到匹配条件时立即返回。

正如一些评论者所说,如果可能的话,找到一种简单数字比较的方法也比字符串比较更快。

票数 2
EN

Stack Overflow用户

发布于 2015-02-17 18:38:02

编写自己的循环而不是linq,看看它是如何执行的:

注意:这段代码假设ips集合中总是有两个IP地址,正如对问题的注释中所述。

代码语言:javascript
复制
foreach(var device in Devices)
{
      if(device.IPaddress1 == ips[0] || device.IPaddress2 == ips[0] || device.IPaddress3 == ips[0] || device.IPaddress1 == ips[1] || device.IPaddress2 == ips[1] || device.IPaddress3 == ips[1] )
      return device;
}

这将展开其中一个循环,并利用能够在找到匹配时立即返回的优点。

可以通过让数据库来执行进一步的优化。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28568494

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档