我有以下LINQ查询。
大约有55 000件物品的清单。我需要对条目中属性的三个进行搜索。
这是我的代码:
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。
发布于 2015-02-17 18:56:56
与其拥有一个包含所有3个IP地址的字典,不如使用3个字典:
private List<Device> Devices = new List<Device>();
private Dictionary<string, Device> mapIP1;
private Dictionary<string, Device> mapIP2;
private Dictionary<string, Device> mapIP3;在执行搜索之前,您必须初始化它们:
public void InitializeDictionaries()
{
mapIP1 = Devices.ToDictionary(x => x.IPaddress1);
mapIP2 = Devices.ToDictionary(x => x.IPaddress2);
mapIP3 = Devices.ToDictionary(x => x.IPaddress3);
}搜索本身可以使用TryGetValue
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>不能处理重复的键。
发布于 2015-02-17 18:37:20
var device =
Devices.FirstOrDefault(
x => ips.Contains(x.IPaddress1)
|| ips.Contains(x.IPaddress2)
|| ips.Contains(x.IPaddress3));在最坏的情况下(不匹配),将枚举ips三次。我会把它改写为:
var device =
Devices.FirstOrDefault(
x => ips.Any(y => y == x.IPaddress1
|| y == x.IPaddress2
|| y == x.IPaddress3);因此,它只枚举一次,检查每个可能的“匹配条件”,并在找到匹配条件时立即返回。
正如一些评论者所说,如果可能的话,找到一种简单数字比较的方法也比字符串比较更快。
发布于 2015-02-17 18:38:02
编写自己的循环而不是linq,看看它是如何执行的:
注意:这段代码假设ips集合中总是有两个IP地址,正如对问题的注释中所述。
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;
}这将展开其中一个循环,并利用能够在找到匹配时立即返回的优点。
可以通过让数据库来执行进一步的优化。
https://stackoverflow.com/questions/28568494
复制相似问题