.net字典和查找添加/更新

时间:2010-04-12 07:11:47

标签: c# collections

我厌倦了为我所拥有的各种代码做这样的代码块:

if (dict.ContainsKey[key]) {  
    dict[key] = value;  
}  
else {  
    dict.Add(key,value);  
}

和查找(即键 - >值列表)

if (lookup.ContainsKey[key]) {  
    lookup[key].Add(value);  
}  
else {  
    lookup.Add(new List<valuetype>);  
    lookup[key].Add(value);  
}  

我是否应该使用另一个集合库或扩展方法在一行代码中执行此操作,无论键和值类型是什么?

e.g。

dict.AddOrUpdate(key,value)  
lookup.AddOrUpdate(key,value)

6 个答案:

答案 0 :(得分:34)

正如Evgeny所说,索引器已经取代现有的值 - 所以如果只是想要无条件地设置给定键的值,你可以做

dictionary[key] = value;

更有趣的案例是“获取一个值,或者在必要时插入它”。使用扩展方法很容易:

public static TValue GetOrCreateValue<TKey, TValue>
    (this IDictionary<TKey, TValue> dictionary,
     TKey key,
     TValue value)
{
    return dictionary.GetOrCreateValue(key, () => value);
}

public static TValue GetOrCreateValue<TKey, TValue>
    (this IDictionary<TKey, TValue> dictionary,
     TKey key,
     Func<TValue> valueProvider)
{
    TValue ret;
    if (!dictionary.TryGetValue(key, out ret))
    {
        ret = valueProvider();
        dictionary[key] = ret;
    }
    return ret;
}

注意使用委托创建默认值 - 这有助于像“list as value”这样的场景;你不想创建空列表,除非你必须:

dict.GetOrCreateValue(key, () => new List<int>()).Add(item);

另请注意,如果密钥已经存在,这只会执行一次查找 - 无需执行ContainsKey然后查找值。在创建新值时,它仍然需要两次查找。

答案 1 :(得分:14)

更新时,您无需执行检查。只需使用:

dict[key] = value

它将取代任何现有价值。遗憾的是,在检索值时,没有方便的单一方法(如Python中的setdefault),但您可以创建自己的扩展方法。像这样:

if (!lookup.TryGetValue(key, out value))
{
     value = new List<T>();
     lookup.Add(key, value);
}

答案 2 :(得分:4)

.NET 4.0中的ConcurrentDictionary有this nice method。您也可以为此编写扩展方法。

答案 3 :(得分:3)

如果使用.NET Framework 4或更高版本,则可以使用AddOrUpdate Method

dict.AddOrUpdate(key,value)  

添加或更新就像这样

dict[key] = value;

答案 4 :(得分:1)

我不确定是否有一个像你要求的方法,但是你可以为它编写一个小函数,或者使用try catch异常,大概如果你尝试添加一个已存在的值,它将抛出一个异常。如果你抓住它并忽略它......只是一个建议

答案 5 :(得分:0)

我喜欢Travis SettingsAddOrUpdate方法,但我也喜欢字典集合的表现:)所以,这是实现ConcurrentDictionary的所有类的扩展方法。

public static TValue AddOrUpdate<TKey, TValue>(
    this IDictionary<TKey, TValue> dict,
    TKey key,
    TValue addValue,
    Func<TKey, TValue, TValue> updateValueFactory)
{
    TValue existing;
    if (dict.TryGetValue(key, out existing))
    {
        addValue = updateValueFactory(key, existing);
        dict[key] = addValue;
    }
    else
    {
        dict.Add(key, addValue);
    }

    return addValue;
}


public static TValue AddOrUpdate<TKey, TValue>(
    this IDictionary<TKey, TValue> dict,
    TKey key,
    Func<TKey, TValue> addValueFactory,
    Func<TKey, TValue, TValue> updateValueFactory)
{
    TValue existing;
    if (dict.TryGetValue(key, out existing))
    {
        existing = updateValueFactory(key, existing);
        dict[key] = existing;
    }
    else
    {
        existing = addValueFactory(key);
        dict.Add(key, existing);
    }

    return existing;
}