匹配日期范围的字典键

时间:2010-07-30 18:08:29

标签: c# collections dictionary

我想将数据存储在通用字典中,其中的键与日期范围相匹配。

例如,我提出了以下想法

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方法的查找期间使用它。

我想知道是否还有其他人想出这个问题的优雅解决方案?

我应该提一下,我将首先匹配密钥,然后可能会有特定密钥属性的日期范围。

2 个答案:

答案 0 :(得分:7)

您的Equals实施违反了guidelines for overriding Equals。特别是您的实现不满足传递性规则:

  
      
  • 如果x.Equals(y) && y.Equals(z)返回true,则x.Equals(z)返回true。
  •   

违反此指南是一个坏主意,可能会导致问题和混乱。我建议你不要这样做。

我会避免将间隔作为密钥存储在字典中。如果您愿意,可以将特定键的间隔列表作为放在字典中,但它不应该是键的一部分。

当您搜索查找间隔时,您可以先使用字典键获取该键的间隔列表,然后迭代间隔以找到与您的参数重叠的间隔。如果特定键的间隔不重叠,则可以对它们进行排序并使用二进制搜索来查找特定间隔。如果特定键的间隔可以重叠,您可以查看其他数据结构,例如interval tree

相关问题

答案 1 :(得分:1)

对于getHashCode,返回this.StartDatethis.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);

使用上面的静态方法,您不再需要重叠键的概念。