如何快速过滤满足日期范围条件的对象

时间:2011-08-06 18:38:15

标签: c# collections filtering date-range

我有大量的对象

public class Restriction
{
    // which days this restriction applies to
    public DateTime From { get; set; }
    public DateTime To { get; set; }

    // valid applicable restriction range
    public int Minimum { get; set; }
    public int Maximum { get; set; }
}

我可以拥有

IList<Restricton> restrictions;

然后搜索在特定日期应用的限制

restrictions.Where(r => day >= r.From && day <= r.To);

问题

我认为使用IList<T>不是最佳选择,因为我会对这些限制进行大量搜索,每次调用LINQ方法.Where时,都会枚举和过滤整个集合

从SQL知识我知道表扫描总是比索引扫描更糟,所以我想在这里应用类似的逻辑。每次我宁愿以更聪明的方式过滤时,而不是枚举整个集合。

问题

什么是更好(更快)的方式来枚举我的限制,所以每次我想过滤掉一些时,我的算法都不会枚举它们?

我在考虑IDictionary<K,V>,但它仍然需要扫描它们,因为我的限制不是每天设定,而是每天设定。

你会建议什么?

4 个答案:

答案 0 :(得分:3)

考虑按From排序列表 - 然后您可以快速执行二进制搜索,以找到可能适用于From的限制子集。

您可能还希望获得To排序的第二个列表副本 - 然后,您可以再次执行二进制搜索,以查找我在To方面适用的限制子集。使用这两个列表,您可以执行两个二进制搜索,并确定哪个集更小,并且只考虑该集。

可能有一个更好的选择,但这是一个良好的开端,我现在没有精力去做更好的事情:(

答案 1 :(得分:2)

您需要的是两个排序列表,以模拟数据库对索引执行的操作,因为在排序列表中搜索某些内容非常快。

第一个列表应该按From属性排序,哈希到第二个列表中,按To属性排序。这与数据库的功能类似。

.Net中的已排序列表

.Net有一个类可以进行名为SortedList的键控和位置访问,您可以使用它来实现您想要的目标。

您可以使用带有IComparer的构造函数来表明SortedList应如何比较您的Restriction类。您需要编写两个IComparers代码,一个比较From属性,另一个比较To属性。

答案 2 :(得分:0)

如果您有很多查询而没有那么多插入,则可以执行以下操作: 创建两个对象的排序列表,一个按fromDate排序,另一个按toDate排序。然后,您可以对sortedLists执行快速搜索,以查找每个List,一组有效结果(在第一个列表中查询具有fromDate <= searchDate的条目,在第二个列表中查询toDate >= searchDate)。然后加入结果集以获得结果。

答案 3 :(得分:0)

这种问题的一个常见解决方案是实现分区;这是在数据库环境中实现的,以减少搜索空间。唯一需要注意的是,您的集合无法使用其他条件进行过滤,或者您需要构建索引。

示例实现可能会使用一组包含特定日期范围的列表(按月(s),年(s)等)。执行插入时,您可以确定正确的列表并将项目放在该列表中。执行搜索时,您可以轻松确定正确的列表或列表集,然后仅在这些列表中执行扫描。

但是,您还应该考虑这个问题 - 您将处理多少元素?当元素数量非常大时,扫描整个列表只会成为一个严重的问题。如果你不处理过多的数据,那么优化这个问题还为时过早。