C#binarysearch由T的成员列出

我有一个带有DateTime成员TimeStamp的基类Event 。 许多其他事件类将源于此。

我希望能够快速搜索事件列表,所以我想使用二进制搜索。

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

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

 public class EventList : List where T : Event { private IComparer comparer = (x, y) => Comparer.Default.Compare(x.TimeStamp, y.TimeStamp); public IEnumerable 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的成员TimeStamp进行搜索。

什么是接近这个的好方法?

我认为你已经使用comparerfunction正确的方式了。 它通过比较两个T的日期来比较它们。

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

另外,只是为了确保:列表是否按时间字段排序? 否则binarysearch将无效。

编辑

这个问题比我想象的要复杂得多。 一个可以帮助您的解决方案是:

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

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

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

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

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

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

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

如果您的Event类包含要排序的属性,那么您的方法就可以了。 然后,编译器可以validation传入的T是什么,它将从Eventinheritance并包含DateTime属性。 如果Event不包含DateTime属性,您可能希望将其添加到事件,或将T约束为更具体的类型,其中包含搜索所需的属性。

请务必确保在应用BinarySearch之前对列表进行排序。

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

也许您可以考虑使用SortedList作为基类而不是List。 然后,您可以使用IndexOfKey方法搜索指定的TimeStamp。 该方法进行二分查找。