Многоключевой словарь с дополнительными клавишами - PullRequest
3 голосов
/ 26 августа 2011

Мне нужен словарь с несколькими ключами 2 разных типов (int и string, оба уникальные, поэтому они могут появляться только внутри 1 ключа).Вот пример: информация о группе (GroupInfo) может запрашиваться либо по GroupdId, либо по одному из имен членов:


GroupId   MemberNames           GroupInfo
{1,       John, Mary, Joe} ==>  {GroupInfo}

Таким образом, информация о группе должна возвращаться по запросу либо по id (1), либо по одному изимена членов (Джон).

Моим первым решением было создание ключа, который оборачивает GroupdId и MemberNames с переопределенным методом Equals, который сравнивает GroupIds и просматривает список членов.Однако, чтобы сделать эти записи равными:


GroupId   MemberNames          
{0,       John}
{1,       null}
{1,       Mary}

GetHashCode должен возвращать то же самое значение константы.Это приведет к тому, что словарь станет связанным списком, а производительность снизится до O (N) в лучшем случае.

Другое решение состоит в том, чтобы хранить 2 словаря отдельно: GroupId ==> GroupInfo, MemberName ==> GroupInfo.

Есть еще идеи?

Ответы [ 2 ]

4 голосов
/ 26 августа 2011

На основании того, что вы описали в своем комментарии

как вы удалили по ключу? Например, при наличии ключа «Джон» все остальные ключи также должны быть удалены.

Возможно, теперь вам стало ясно, что «Словарь» - это не то, что вы ищете. Главным образом потому, что вам нужно несколько ключей и вам необходимо сопоставить ключи с другими ключами.

Таким образом, вы можете создать свой собственный класс, который реализует IDictionary. В основном следующим образом.

    class MultiKeyDictionary : IDictionary
{
    Dictionary<string, GroupInfo> stringDict = new Dictionary<string, GroupInfo>();
    Dictionary<int, GroupInfo> intDict = new Dictionary<int, GroupInfo>();
    Dictionary<GroupInfo, List<object>> keysDict = new Dictionary<GroupInfo, List<object>>();

    //Each of these would add to their own dictionary, as well as adding the backwards
    //entry in the "keysDict"
    public void Add(string memberName, GroupInfo value);
    public void Add(int key, GroupInfo value);

    public bool Contains(string key);
    public bool Contains(int key);

    //This would be the enumerator of the "keys" of "keysDict"
    //because it is actually a list of all GroupInfos
    public IDictionaryEnumerator GetEnumerator()

    public ICollection NameKeys;
    public ICollection GroupIDKeys;
    //This is to adhere to the interface. It should be carefully commented or even deprecated.
    public ICollection Keys;

    //For this, you look up the GroupInfo for the key, then do
    //foreach(object key in keysDict[<groupInfoIJustLookedUp>]) {
    //   if(key.gettype == typeof(string) stringDict.Remove(key);
    //   else if (key.gettype == typeof(int) intDict.Remove(key);
    //   else //WHAT?!?
    //}
    public void Remove(string key);
    public void Remove(int key);

    //This would be the "Keys" collection of the "keysDict"
    public ICollection Values;

    //etc... etc...
    public object this[string memberName];
    public object this[int groupId];
}
2 голосов
/ 27 августа 2011

Чтобы сохранить только 1 словарь, рассмотрите возможность преобразования GroupId (int) в строку и использования его в качестве ключа (число 'keys' не должно конфликтовать с именными ключами).Сохраните ссылки на ключи, чтобы в случае их удаления все остальные были удалены.

...