C# 二进制搜索列表由 T 的成员

发布于 2024-08-27 15:42:21 字数 794 浏览 5 评论 0原文

我有一个带有 DateTime 成员 TimeStamp 的基类 Event 。 许多其他事件类将从中派生。

我希望能够快速搜索事件列表,因此我想使用二分搜索。

(列表数据按时间戳排序,但同时发生的事件可能有重复的时间戳)

所以我开始写这样的东西:

public class EventList<T> : List<T> where T : Event
{
   private IComparer<T> comparer = (x, y) => Comparer<DateTime>.Default.Compare(x.TimeStamp, y.TimeStamp);

   public IEnumerable<T> EventsBetween(DateTime inFromTime, DateTime inToTime)
   {
       // Find the index for the beginning. 
       int index = this.BinarySearch(inFromTime, comparer);

       // BLAH REST OF IMPLEMENTATION
   }
}

问题是 BinarySearch 只接受 T (所以 - 一个 Event 类型)作为参数,而我想基于 T 的成员 - 时间戳进行搜索。

解决这个问题的好方法是什么?

I have a baseclass Event with a DateTime member TimeStamp.
Lots of other event-classes will derive from this.

I want to be able to search a list of events fast, so I'd like to use a binary search.

(The list-data is sorted on timestamp, but there might be duplicate timestamps for events that occurred simultaneously)

So I started out writing something like this :

public class EventList<T> : List<T> where T : Event
{
   private IComparer<T> comparer = (x, y) => Comparer<DateTime>.Default.Compare(x.TimeStamp, y.TimeStamp);

   public IEnumerable<T> EventsBetween(DateTime inFromTime, DateTime inToTime)
   {
       // Find the index for the beginning. 
       int index = this.BinarySearch(inFromTime, comparer);

       // BLAH REST OF IMPLEMENTATION
   }
}

The problem is that the BinarySearch only accepts T (so - an Event type) as parameter, while I want to search based on a member of T - the TimeStamp.

What would be a good way to approach this ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

白色秋天 2024-09-03 15:42:21

我认为您的 comparer 功能已经走在正确的道路上。它通过比较两个 T 的日期来进行比较。

要处理 BinarySearchinFromTime 参数,您可以创建一个具有正确 TimeStamp 的虚拟事件,并将该虚拟事件传递给 BinarySearch.

另外,只是为了确保:列表是否按时间字段排序?否则二分查找将无法工作。

编辑

这个问题比我最初想象的更复杂。一个对您有帮助的解决方案是:

  • 创建一个适配器类,将您的 EventList 公开为 IList。
  • 使用 IList 上的 BinarySearch 扩展方法进行搜索。

不幸的是,没有内置的 BinarySearch 扩展方法,所以你必须自己写。如果您编写自己的搜索,则可能不值得花费额外的精力将其放入扩展方法中。在这种情况下,您自己在 EventList 类中实现自定义 BinarySearch 算法可能是最好的选择。

另一种选择是,如果有一种 BinarySearch 接受从 T 中提取相关密钥的委托,但这也不可用。

I think that you already are on the right way with your comparer function. It compares two T's by comparing the dates of them.

To handle the inFromTime parameter to BinarySearch you can create a dummy Event which has the correct TimeStamp and pass that dummy to BinarySearch.

Also, just to make sure: Is the list sorted on the time field? Otherwise binarysearch won't work.

Edit

This problem is more complex than I first thought. A solution that would help you is:

  • Make an adapter class which exposes your EventList as an IList.
  • Use a BinarySearch extension method on IList to do the search.

Unfortunately there is no built in BinarySearch extension method, so you will have to write your own. In case you write your own search it might not be worth the extra effort to put it in an extension method. In that case just implementing a custom BinarySearch algorithm yourself in your EventList class is probably the best you can do.

Another option would be if there was a form of BinarySearch that accepted a delegate that extracts the relevant key from T, but that is not available either.

无风消散 2024-09-03 15:42:21

最简单的方法是定义一个实现 IComparer 的小帮助器类。

public class CompUtil : IComparer<T> {
  public int Compare(T left, T right) { 
    return left.TimeStamp.CompareTo(right.TimeStamp);
  }
}

然后您可以按如下方式使用它

int index = this.BinarySearch(inFromTime, new CompUtil());

The easiest way is to define a small helper class which implements IComparer<T>.

public class CompUtil : IComparer<T> {
  public int Compare(T left, T right) { 
    return left.TimeStamp.CompareTo(right.TimeStamp);
  }
}

You can then use it as follows

int index = this.BinarySearch(inFromTime, new CompUtil());
汹涌人海 2024-09-03 15:42:21

如果您的 Event 类包含您想要排序的属性,那么您的方法就可以了。然后,编译器可以验证传入的任何 T 是否都将从 Event 继承并包含 DateTime 属性。如果 Event 不包含 DateTime 属性,您可能希望将其添加到事件中,或将 T 限制为更具体的类型,其中包含搜索所需的属性。

请记住在应用二进制搜索之前确保您的列表已排序。

If your Event class contains the property you want to sort on, your approach will be fine. The compiler can then verify that whatever T is being passed in, it will inherit from Event and contain the DateTime property. If Event does not contain the DateTime property, you would probably want to add it to event, or constrain T to be a more specific type, which contains the property needed for your search.

Remember to make sure your list is sorted before applying BinarySearch.

慵挽 2024-09-03 15:42:21
public class EventList<TEvent, TData>
   : List<TEvent> where TEvent : Event, TData: DataTime
{
   class Comparer : IComparer<TData> { } // as JaredPar mentioned above

   public IEnumerable<TEvent> EventsBetween(TData from, TData to) { }
}
public class EventList<TEvent, TData>
   : List<TEvent> where TEvent : Event, TData: DataTime
{
   class Comparer : IComparer<TData> { } // as JaredPar mentioned above

   public IEnumerable<TEvent> EventsBetween(TData from, TData to) { }
}
楠木可依 2024-09-03 15:42:21

也许您可以考虑使用 SortedList 作为基类而不是列表。然后,您可以使用 IndexOfKey 方法搜索指定的时间戳。该方法进行二分搜索。

Maybe you could consider using SortedList as base class instead of List. You could then use IndexOfKey method to search for a specified TimeStamp. That method does a binary search.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文