我想将数据存储在通用字典中,其中的键与日期范围相匹配。
例如,我提出了以下想法
public class MyKey : IEquatable<MyKey>
{
public int Key { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public override int GetHashCode()
{
returns Key;
}
// if there is overlap in date range consider them equal
public bool Equals(MyKey other)
{
if (Key!=other.Key)
return false;
else if(other.StartDate >=StartDate && other.StartDate <=EndDate)
return true;
else if(other.EndDate >=StartDate && other.EndDate <=EndDate)
return true;
else if(StartDate >=other.StartDate && StartDate <=other.EndDate)
return true;
else if(EndDate >=other.StartDate && EndDate <=other.EndDate)
return true;
else
return false;
}
}
然后我会像这样使用词典
var dict = new Dictionary<MyKey,MyClass>();
Populate(dict);
// get an element where the current date is in the daterange of the key
// in the collection
var key = new MyKey();
key.Key=7;
key.StartDate=DateTime.Now;
key.EndDate=key.StartDate;
// retrieve the matching element for the date
var myclass = dict[key];
这是我能想到的最好的结果,但是这样做似乎很奇怪。我想添加一个名为选择日期的第四个属性。并且会在字典中的条目中将其设置为null,但会在Equals方法的查找期间使用它。
我想知道是否还有其他人想出这个问题的优雅解决方案?
我应该提一下,我将首先匹配密钥,然后可能会有特定密钥属性的日期范围。
答案 0 :(得分:7)
您的Equals实施违反了guidelines for overriding Equals。特别是您的实现不满足传递性规则:
- 如果
x.Equals(y) && y.Equals(z)
返回true,则x.Equals(z)
返回true。
违反此指南是一个坏主意,可能会导致问题和混乱。我建议你不要这样做。
我会避免将间隔作为密钥存储在字典中。如果您愿意,可以将特定键的间隔列表作为值放在字典中,但它不应该是键的一部分。
当您搜索查找间隔时,您可以先使用字典键获取该键的间隔列表,然后迭代间隔以找到与您的参数重叠的间隔。如果特定键的间隔不重叠,则可以对它们进行排序并使用二进制搜索来查找特定间隔。如果特定键的间隔可以重叠,您可以查看其他数据结构,例如interval tree。
相关问题
答案 1 :(得分:1)
对于getHashCode,返回this.StartDate
和this.EndDate
以及this.Key
的哈希值。有关简单的哈希想法,请参阅this page。有更好的散列方法,但该页面应该让你开始。
添加一个静态方法,它接受一个int键和一个DateTime,因为它似乎就是你使用它的方式。 (如果需要,可以在一个范围内使用两个DateTimes)
return myDictionary[myDictionary.Keys.Find(x=> value < x.EndDate && value > x.StartDate) && x.Key = key];
两个日期:
return myDictionary[myDictionary.Keys.Find(x=> ((date1 < x.EndDate && date1 > x.StartDate)) || (date2 < x.EndDate && date2 > x.StartDate))) && x.Key = key];
如果您使用范围,可以将其中任何一个设为全部查找,因为可能存在碰撞。
将您的平等条件更改为
return this.StartDate.Equals(o.StartDate) && this.EndDate.Equals(o.EndDate) && this.Key.Equals(o.Key);
使用上面的静态方法,您不再需要重叠键的概念。