代码之家  ›  专栏  ›  技术社区  ›  Jeff

在日期范围内匹配的字典键

  •  3
  • Jeff  · 技术社区  · 15 年前

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

    例如,我想出了以下想法

    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];
    

    这是我能想到的最好的方法,不过这看起来很笨拙。我想添加第四个属性,叫做选择日期。并在字典的条目中将其设置为空,但在equals方法的查找期间将使用它。

    我想知道是否有人想出了一个优雅的解决方案来解决这个问题?

    我应该提到,我将首先匹配键,然后可能有特定键属性的日期范围。

    2 回复  |  直到 15 年前
        1
  •  1
  •   Jack    15 年前

    对于GetHashCode,返回的哈希值为 this.StartDate this.EndDate this.Key . 见 this page 对于简单的哈希思想。现在有更好的散列方法,但该页面应该可以让您开始。

    添加一个静态方法,它接受一个int键和一个datetime,因为您似乎就是这样使用它的。(如果需要的话,一个范围可能需要两个日期时间) 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);

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

        2
  •  7
  •   Community CDub    8 年前

    您对equals的实现违反了 guidelines for overriding Equals . 尤其是您的实现不满足传递性规则:

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

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

    我会避免把间隔作为关键字存储在字典中。您可以将特定键的间隔列表作为 价值 如果你喜欢的话,在字典里,但它不应该是关键字的一部分。

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

    相关问题