Ключи словаря, которые соответствуют диапазону дат - PullRequest
3 голосов
/ 30 июля 2010

Я хотел бы хранить данные в Универсальном словаре с ключами, которые совпадают с диапазонами дат.

Например, я пришел к следующей идее

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 ]

7 голосов
/ 30 июля 2010

Ваша реализация Equals нарушает правила для переопределения Equals .В частности, ваша реализация не удовлетворяет правилу транзитивности:

  • , если x.Equals(y) && y.Equals(z) возвращает true, тогда x.Equals(z) возвращает true.

Breakingэта рекомендация является плохой идеей и может привести к проблемам и путанице.Я бы порекомендовал вам этого не делать.

Я бы не стал хранить интервалы в качестве ключей в словаре.Вы можете поместить список интервалов для определенного ключа как значение в словаре, если хотите, но он не должен быть частью ключа.

Когда вы ищете, чтобы найтиинтервал, вы можете сначала использовать ключ словаря, чтобы получить список интервалов для этого ключа, а затем выполнить итерацию по интервалам, чтобы найти интервал, совпадающий с вашим параметром.Если интервалы не перекрываются для определенного ключа, вы можете отсортировать их и использовать двоичный поиск, чтобы найти определенный интервал.Если интервалы для определенного ключа могут перекрываться, вы можете посмотреть на другие структуры данных, такие как дерево интервалов .

Смежный вопрос

1 голос
/ 30 июля 2010

Для getHashCode вернуть хэш this.StartDate и this.EndDate и this.Key.См. эту страницу для простых идей хеширования.Существуют более совершенные методы хеширования, но эта страница должна помочь вам начать работу.

Добавьте статический метод, который принимает ключ int и один DateTime, поскольку кажется, что именно так вы и используете.(это может занять два 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);

Используя вышеописанный статический метод, вам больше не нужно понятие перекрывающихся ключей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...