【问题标题】:most efficient way to query a collection - c#查询集合的最有效方法 - C#
【发布时间】:2012-10-14 07:16:43
【问题描述】:

我正在搜索包含 3 列的通用列表(或 IQueryable)。我正在尝试根据 1 和 2 查找第 3 列的值,但搜索速度确实很慢。对于单个搜索,速度并不明显,但我正在循环执行此搜索,并且对于 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 创建了一个字典,其中startend 作为键。我认为这可能是正确的解决方案。

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);

工作正常 - 更快

【问题讨论】:

  • 似乎是索引的明显问题。如果字典中的值被排序不会更快吗?
  • 是的,我认为字典中的 2 列键可能是一个很好的方法。我需要调查一下

标签: c# asp.net-mvc linq


【解决方案1】:

您的问题是每次返回项目时 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;
}

【讨论】:

  • 嗨,Jan,感谢这个愚蠢的问题,但是我如何将 KeyValuePair 传递给该方法?我正在尝试这个,但出现错误:FindByStartAndEnd(new IEnumerable&lt;KeyValuePair&lt;5, 20&gt;&gt;, distanceList)?
  • 您创建一个包含所有开始和结束整数的 KeyValuePair 列表,并将其传递给方法。
【解决方案2】:

从前两列中创建一个值,例如将它们连接成 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) 操作循环遍历项目以找到一个有很大的不同。

【讨论】:

    【解决方案3】:

    我会试试hashSet。这应该会加快速度;)

    【讨论】:

      【解决方案4】:

      如果你可以控制你的集合和模型类,有一个库可以让你索引类的属性,这可以大大加快搜索速度。

      http://i4o.codeplex.com/

      【讨论】:

        【解决方案5】:

        创建一个字典,其中第 1 列和第 2 列创建键。您创建字典一次,然后您的搜索将几乎是即时的。

        【讨论】:

        • 好的,我已经启动并运行了它,它可以很好地填充字典。我会将代码添加到原始帖子中作为更新。但是,它无法识别密钥并且找不到正确的条目。你知道如何为此创建一个相等比较器吗?
        • @e-on:尝试最简单的解决方案 - 将密钥创建为字符串 col1-col2。如果这开始起作用,请尝试尝试例如元组。
        • 谢谢 empi - 我搞定了。结果,问题不在于元组,而在于我的一些数据行。现在这是一个非常快速的解决方案:)
        猜你喜欢
        • 2015-04-08
        • 1970-01-01
        • 1970-01-01
        • 2014-07-11
        • 2019-08-25
        • 1970-01-01
        • 1970-01-01
        • 2013-05-11
        • 1970-01-01
        相关资源
        最近更新 更多