我有大量的对象
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>
,但它仍然需要扫描它们,因为我的限制不是每天设定,而是每天设定。
你会建议什么?
答案 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)等)。执行插入时,您可以确定正确的列表并将项目放在该列表中。执行搜索时,您可以轻松确定正确的列表或列表集,然后仅在这些列表中执行扫描。
但是,您还应该考虑这个问题 - 您将处理多少元素?当元素数量非常大时,扫描整个列表只会成为一个严重的问题。如果你不处理过多的数据,那么优化这个问题还为时过早。