在Dictionary <key,collection <value =“”>&gt; </key,>中自动创建集合

时间:2010-01-29 07:01:12

标签: c# .net collections dictionary

很多时候我必须创建一个Dictionary<KeyType, List<ValueType>>

在我开始使用字典之前,我必须先验证是否已为该密钥创建了List。

//Can i remove these two lines?
if(!dict.ContainsKey(key)) 
    dict[key]= new List<ValueType>;

//now use the key
dict[key].Add(value);

我知道它只有“2行”的代码,但它让我烦恼,我认为它可以删除。

我可以在某种程度上扩展字典,但在此之前,我想知道是否有人找到了一种聪明的方法来删除上述if语句。

基本上我想创建一个Dictionary<KeyType, Collection<ValueType>>并立即开始使用dict[key].Add(value)

4 个答案:

答案 0 :(得分:7)

你可以像Google Java Collection的Multimap那样创建...或者你可以添加这样的扩展方法:

public static void AddValue<TKey, TValue>
    (this IDictionary<TKey, List<TValue>> dictionary, TKey key, TValue value)
{
    List<TValue> values;
    if (!dictionary.TryGetValue(key, out values))
    {
        values = new List<TValue>();
        dictionary.Add(key, values);
    }
    values.Add(value);
}

正如Bevan所说,Lookup也可以提供帮助 - 但您只能使用ToLookup方法创建一个,之后就无法对其进行修改。在许多情况下,这是一件非常好的事情,但是如果你需要一个可变的地图,那么你就会得到类似上面的内容。

答案 1 :(得分:2)

看看.NET 3.5中Linq引入的LookUp类 - 它可能正是您所寻找的:一个Dictionary类,每个键支持多个项目。

也许唯一重要的缺点是你必须在一个批次中拥有所有元素,因为LookUp是不可变的。

答案 2 :(得分:2)

ConcurrentDictionary<T,K>.GetOrAdd方法非常有用。

private ConcurrentDictionary<string, ICollection<int>> _dictionary;

private static ICollection<int> CreateEmptyList(string dummyKey)
{
    return new List<int>();
}

private void AddValue(string key, int value)
{
    ICollection<int> values = _dictionary.GetOrAdd(key, CreateEmptyList);
    values.Add(value);
}

编辑:以下是如何将该功能实现为IDictionary<T,K>(C#3)的扩展方法的示例:

请注意,IDictionary<TKey, TValue>通常不是线程安全的,因此如果您希望使用此扩展方法保证线程安全,则必须像其他操作一样手动实现它。

public static TValue GetOrAdd<TKey, TValue>(
    this IDictionary<TKey, TValue> dictionary,
    TKey key,
    Func<TKey, TValue> valueFactory)
{
    TValue value;
    if (!dictionary.TryGetValue(key, out value))
    {
        value = valueFactory(key);
        dictionary.Add(key, value);
    }

    return value;
}

答案 3 :(得分:1)

要添加答案,您还可以添加一个更通用的扩展,它接受委托进行实例化:

public static TValue GetOrCreate<TKey, TValue>
    (this IDictionary<TKey, TValue> dict, 
          TKey key, 
          Func<TKey, TValue> getValue)
{
    TValue value;
    if (!dict.TryGetValue(key, out value))
    {
        dict.Add(key, getValue(key));
    }
    return value;
}

然后你可以提供你喜欢的任何实例化方法:

Dictionary<int, string> dict = new Dictionary<int, string>();
string result = dict.GetOrCreate(5, i => i.ToString());