【问题标题】:Searching with Linq使用 Linq 进行搜索
【发布时间】:2011-02-27 09:32:27
【问题描述】:

我有一个对象集合,每个对象都有一个 int Frame 属性。给定一个 int,我想在集合中找到具有最近 Frame 的对象。

这是我目前正在做的事情:

public static void Search(int frameNumber)
{
    var differences = (from rec in _records
                       select new { FrameDiff = Math.Abs(rec.Frame - frameNumber), Record = rec }).OrderBy(x => x.FrameDiff);

    var closestRecord = differences.FirstOrDefault().Record;

    //continue work...
}

这很好,一切都很好,除了我的收藏中有 200,000 件物品,而且我经常调用这个方法。有没有一种相对简单、更有效的方法来做到这一点?

【问题讨论】:

  • 这只是 LINQ to a collection of objects 还是 LINQ to SQL?
  • “我有一个对象的集合”,问题的第一句话。 ;)

标签: c# linq optimization search performance


【解决方案1】:

您可能想尝试将帧存储在按Frame 排序的数据结构中。然后,当您需要找到最接近给定 frameNumber 的帧时,您可以进行二分查找。

【讨论】:

  • 也许将 SortedList 集合作为您的数据结构。
  • 在 linq 中做这件事不是重点吗?这将是怎样的 linq?代码示例?
  • 我可以接受不使用 linq 的解决方案。我只是在寻找“简单”。
【解决方案2】:
var closestRecord = _records.MinBy(rec => Math.Abs(rec.Frame - frameNumber));

使用来自 MoreLINQ 的 MinBy。

【讨论】:

    【解决方案3】:

    您可以将您的陈述合并为一个 ala:

    var closestRecord = (from rec in _records
                       select new { FrameDiff = Math.Abs(rec.Frame - frameNumber), 
                       Record = rec }).OrderBy(x => x.FrameDiff).FirstOrDefault().Record;
    

    【讨论】:

    • 我认为他的问题是排序(实际上不需要)需要很长时间。
    【解决方案4】:

    也许您可以将您的大项目列表分成 5 到 10 个较小的列表,这些列表由它们的 Framediff 或其他东西排序?

    如果您知道需要在哪个列表中搜索,这样搜索会更快

    【讨论】:

      【解决方案5】:

      我不知道我会为此使用 LINQ,至少不会使用 orderby。

      static Record FindClosestRecord(IEnumerable<Record> records, int number)
      {
          Record closest = null;
          int leastDifference = int.MaxValue;
      
          foreach (Record record in records)
          {
              int difference = Math.Abs(number - record.Frame);
              if (difference == 0)
              {
                  return record; // exact match, return early
              }
              else if (difference < leastDifference)
              {
                  leastDifference = difference;
                  closest = record;
              }
          }
      
          return closest;
      }
      

      【讨论】:

      • 这几乎就是 MoreLINQ 的 MinBy 方法(如 dtb 的回答中所建议的那样)的工作原理。 (尽管MinBy 不能特例提前退出以实现完全匹配。)
      • 如果你有一个排序的集合,你可以有一个更好的提前退出。另外,如果您使用“for”循环,您可以记住上次使用的索引并从那里开始搜索,而不是从集合的开头开始。简单和快速之间的良好平衡。这就是我最终选择做的事情,效果很好。
      猜你喜欢
      • 2013-01-27
      • 1970-01-01
      • 2011-11-07
      • 1970-01-01
      • 1970-01-01
      • 2010-09-20
      • 2011-04-07
      • 1970-01-01
      相关资源
      最近更新 更多