我正在搜索包含3列的通用列表(或IQueryable)。我试图找到3列的值,基于1和2,但搜索速度非常慢。对于单个搜索,速度不明显,但我在循环上执行此搜索,并且对于700次迭代,它需要超过2分钟的组合时间,这不是任何用途。第1列和第2列为int
,第3列为double
。这是我正在使用的linq:
public static Distance FindByStartAndEnd(int start, int end, IQueryable<Distance> distanceList)
{
Distance item = distanceList.Where(h => h.Start == start && h.End == end).FirstOrDefault();
return item ;
}
IQueryable列表中可能有60,000个条目。我知道这很多,但我认为这不会给搜索带来任何问题。
所以我的问题是,当需要匹配2列以获得第三列的值时,是否有更好的方法来搜索集合?我想我需要所有700次搜索几乎是即时的,但每次搜索大约需要300毫秒。
更新 - 最终解决方案#######################
我现在使用Tuple
创建了一个字典,其中start
和end
为关键字。我认为这可能是正确的解决方案。
var dictionary = new Dictionary<Tuple<int, int>, double>();
var key = new Tuple<int, int>(Convert.ToInt32(reader[0]), Convert.ToInt32(reader[1]));
var value = Convert.ToDouble(reader[2]);
if (value <= distance)
{
dictionary.Add(key, value);
}
var key = new Tuple<int, int>(5, 20);
工作得很好 - 更快
答案 0 :(得分:5)
创建一个字典,其中第1列和第2列创建密钥。您创建一次字典,然后您的搜索几乎是即时的。
答案 1 :(得分:0)
如果您可以控制集合和模型类,则可以使用一个库来索引类的属性,这可以大大加快搜索速度。
答案 2 :(得分:0)
您的问题是每次返回项目时LINQ都必须执行表达式树。只需使用多个开始值和结束值调用此方法
public static IEnumerable<Distance> FindByStartAndEnd
(IEnumerable<KeyValuePair<int, int>> startAndEnd,
IQueryable<Distance> distanceList)
{
return
from item in distanceList
where
startAndEnd.Select(s => s.Key).Contains(item.Start)
&& startAndEnd.Select(s => s.Value).Contains(item.End)
select item;
}
答案 3 :(得分:0)
我试试hashSet。这应该可以加快速度;)
答案 4 :(得分:0)
从前两列创建单个值,例如将它们连接到long
,并将其用作字典中的键:
public long Combine(int start, int end) {
return ((long)start << 32) | end;
}
Dictionary<long, Distance> lookup = distanceList.ToDictionary(h => Combine(h.Start, h.End));
然后你可以查找值:
public static Distance FindByStartAndEnd(int start, int end, IQueryable<Distance> distanceList) {
Distance item;
if (!lookup.TryGetValue(Combine(start, end), out item) {
item = null;
}
return item;
}
从字典中获取一个项目是接近O(1)操作数,它应该与O(n)操作系统产生显着差异,以循环查找项目。