带有可选键的多键字典

时间:2011-08-25 23:39:58

标签: c# .net-3.5 dictionary hashtable

我需要一个包含2种不同类型的多个键的字典(int和string,两者都是唯一的,因此它们只能出现在1个键中)。下面是一个示例:GroupdId或其中一个成员名称可以查询组信息(GroupInfo):


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

因此,当id(1)或其中一个成员名称(John)请求时,应返回组信息。

我的第一个解决方案是使用重写的Equals方法创建一个包装GroupdId和MemberNames的键,该方法比较GroupIds并查找成员列表。但要使这些条目相等:


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

GetHashCode必须返回相同的const值。这将导致字典成为链接列表,并且在最佳情况下,性能会降低到O(N)查找。

另一个解决方案是分别保留2个词典:GroupId ==> GroupInfo,MemberName ==> ; GROUPINFO

还有其他想法吗?

2 个答案:

答案 0 :(得分:4)

根据您在评论中描述的内容

  

你怎么用钥匙删除?例如,给定键“John”也应删除所有其他键。

现在你可能已经清楚,“词典”并不是你想要的。主要是因为您需要多种密钥类型,并且需要将密钥映射到其他密钥。

因此,您可以创建自己的实现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];
}

答案 1 :(得分:2)

为了只维护1个字典,可以考虑将GroupId(int)转换为字符串并将其用作密钥(数字'keys'不应与名称密钥冲突)。保持对密钥的引用,以便在删除密钥时,其余部分将被删除。