Reputation: 4406
I have a need for a dictionary with multiple keys of 2 different types (int and string, both unique, so they can appear only inside of 1 key). Here is an example: group information (GroupInfo) can be queried by either GroupdId or one of the member names:
GroupId MemberNames GroupInfo
{1, John, Mary, Joe} ==> {GroupInfo}
So group info should be returned when requested by either id (1) or one of the member names (John).
My first solution was to create a key that wraps GroupdId and MemberNames with overridden Equals method that compares GroupIds and looks up a list of members. However to make these entries equal:
GroupId MemberNames
{0, John}
{1, null}
{1, Mary}
GetHashCode has to return the same const value. This will result in a dictionary becoming a linked list and performance degrading to O(N) lookup in the best case scenario.
The other solution is to keep 2 dictionaries separately: GroupId ==> GroupInfo, MemberName ==> GroupInfo.
Any other ideas?
Upvotes: 3
Views: 1791
Reputation: 5828
In order to maintain only 1 dictionary, consider converting the GroupId (int) into a string and use it as a key (number 'keys' should not conflict with name keys). Maintain a references to the keys, so that if one gets deleted, the rest will be deleted.
Upvotes: 1
Reputation: 8316
Based on what you described in your comment
how'd you delete by a key? For example given a key "John" all other keys should be deleted as well.
It may have become clear to you now that a "Dictionary" isn't what you are looking for. Mostly because you have a need for multiple key types, and a need to map keys to other keys.
So you can create your own class that implements IDictionary. Basically as follows.
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];
}
Upvotes: 4