如何快速过滤满足日期范围条件的对象
Posted
技术标签:
【中文标题】如何快速过滤满足日期范围条件的对象【英文标题】:How to fast filter objects that satisfy date range condition 【发布时间】:2011-10-21 13:57:16 【问题描述】:我有大量的对象
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>
,但它仍然需要扫描它们,因为我的限制不是每天设置,而是每天范围。
你有什么建议?
【问题讨论】:
这里的第二个答案可以帮助吗:***.com/questions/1042087/… 见:Interval Tree 【参考方案1】:考虑按From
对列表进行排序 - 然后您可以快速执行二进制搜索以找到可能适用于From
的限制子集。
您可能还希望获得按To
排序的列表的第二个副本-然后,您可以再次执行二进制搜索以查找我适用于To
的限制子集。使用这两个列表,您可以执行 both 二进制搜索,并找出哪个集合更小,然后只考虑那个集合。
可能有更好的选择,但这是一个好的开始,我现在还没有足够的精力去解决更好的事情:(
【讨论】:
【参考方案2】:您需要两个排序列表来模拟数据库对索引的操作,因为在排序列表中搜索内容非常快。
第一个列表应按From
属性排序,散列到第二个列表中,按To
属性排序。这类似于数据库的作用。
.Net 中的排序列表
.Net 有一个名为SortedList 的类可以进行键控和位置访问,您可以使用它来实现您想要的。
您可以使用带有IComparer
的构造函数,您可以使用它来指示SortedList 应该如何比较您的Restriction
类。您将需要编写两个 IComparers,一个用于比较 From 属性,另一个用于比较 To 属性。
【讨论】:
【参考方案3】:如果您有很多查询但插入的次数不多,您可以执行以下操作:
创建两个排序的对象列表,一个按fromDate
排序,另一个按toDate
排序。然后,您可以在 sortedLists 上进行快速搜索,以查找每个列表、有效结果集(在第一个列表中查询带有 fromDate <= searchDate
的条目,在第二个列表中查询 toDate >= searchDate
)。然后加入结果集得到结果。
【讨论】:
【参考方案4】:此类问题的常见解决方案是实现分区;这是在数据库环境中实现的,以减少搜索空间。唯一需要注意的是,您的集合无法使用其他条件进行过滤,否则您需要建立索引。
示例实现可能会使用一组包含特定日期范围(按月、年等)的列表。当您执行插入时,您确定正确的列表并将您的项目放置在该列表中。执行搜索时,您可以轻松确定正确的列表或列表集,然后仅在这些列表中执行扫描。
但是,您还应该考虑这一点——您将处理多少个元素?只有当元素数量非常大时,扫描整个列表才会成为一个严重的问题。如果您不处理大量数据,那么优化这个问题还为时过早。
【讨论】:
以上是关于如何快速过滤满足日期范围条件的对象的主要内容,如果未能解决你的问题,请参考以下文章
使用 and:false 条件 SAPUI5 过滤日期范围的 Odata 服务值