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进行搜索。
什么是接近这个的好方法?
我认为你已经使用comparer
function正确的方式了。 它通过比较两个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。 该方法进行二分查找。