是否有C#数据结构将键映射到多个值?

时间:2010-07-07 18:39:10

标签: c#

是否有C#数据结构将键映射到多个值?我有一个项目集合,我想按名称键入;但是,名称并不是唯一的。 Hashtable和Dictionary只允许使用唯一键。查找似乎接近我想要的;但是,它不可变。

是否存在我缺少的内置数据结构,或者我是否需要自己构建一个?

3 个答案:

答案 0 :(得分:8)

您要找的是multimap

您可能需要查看answer to this question

您可能还想查看C5 Generic Collection library,它是免费的,并且具有多地图的实现。

如果你想要自己动手,一个简单的起点是列表:

Dictionary<TKey,List<TValue>>

但是,你不能以正常方式添加到这样的字典中。您必须首先检查密钥是否已存在,如果是,则获取值(列表)并添加到该密钥。否则,您需要创建列表并使用值填充它。

如果您如此倾向,我建议您考虑使用一组扩展方法来简化添加/删除操作:

public static class MultimapExt
{
    public static void Add<TKey,TValue>( 
        this Dictionary<TKey,List<TValue>> dictionary, TKey key, TValue value )
    {
        List<TValue> valueList;
        if( !dictionary.TryGetValue( key, out valueList )
        {
            valueList = new List<TValue>();
            dictionary.Add( key, valueList );
        }
        valueList.Add( value );
    }

    public static void Remove<TKey,TValue>(
        this Dictionary<TKey,List<TValue>> dictionary, TKey key, TValue value )
    {
        List<TValue> valueList;
        if( dictionary.TryGetValue( key, out valueList ) )
        {
            valueList.Remove( value );
            if( valueList.Count == 0 )
               dictionary.Remove( key ); 
        }
    }
}

答案 1 :(得分:2)

LBushkin's answer是个好人。但是,通过删除不必要的限制来使用Dictionary<TKey, List<TValue>>(这样你也可以使用SortedDictionary<TKey, LinkedList<TValue>>)通过一些精心选择的通用约束,你可以使它更灵活一些:

public static class MultimapExt
{
    public static void Add<TKey, TValue, TCollection>( 
        this IDictionary<TKey, TCollection> dictionary,
        TKey key,
        TValue value
    ) where TCollection : ICollection<TValue>, new()
    {
        TCollection collection;
        if(!dictionary.TryGetValue(key, out collection)
        {
            collection = new TCollection();
            dictionary.Add(key, collection);
        }

        collection.Add(value);
    }

    public static bool Remove<TKey, TValue, TCollection>(
        this IDictionary<TKey, TCollection> dictionary,
        TKey key,
        TValue value
    ) where TCollection : ICollection<TValue>
    {
        TCollection collection;
        if(dictionary.TryGetValue(key, out collection))
        {
            bool removed = collection.Remove(value);

            if(collection.Count == 0)
               dictionary.Remove(key);

            return removed;
        }

        return false;
    }
}

答案 2 :(得分:0)

如何使用字典IList<YOUR_VALUE_TYPE>