.net словарь и поиск добавить / обновить - PullRequest
31 голосов
/ 12 апреля 2010

Мне надоело делать такие блоки кода для различных битов кода, которые у меня есть:

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);  
}  

Есть ли другой набор библиотек или метод расширения, который я должен использовать, чтобы сделать это в одной строке кода независимо от типа ключа и значения?

, например

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

Ответы [ 6 ]

34 голосов
/ 12 апреля 2010

Как говорит Евгений, индексатор уже заменит существующие значения - поэтому, если вы просто хотите безоговорочно установить значение для данного ключа, вы можете сделать

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;
}

Обратите внимание на использование делегата для создания значения по умолчанию, что облегчает такие сценарии, как «список как значение»; Вы не хотите создавать пустой список, если вам не нужно:

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

Также обратите внимание, что поиск выполняется только один раз, если ключ уже присутствует - нет необходимости делать ContainsKey и , тогда ищет значение. Тем не менее, для создания нового значения все еще требуется два поиска.

14 голосов
/ 12 апреля 2010

При обновлении вам не нужно выполнять проверку. Просто используйте:

dict[key] = value

Он заменит любое существующее значение. К сожалению, при получении значения не существует удобного единственного метода (например, setdefault в Python), но вы можете создать свой собственный метод расширения. Как то так:

if (!lookup.TryGetValue(key, out value))
{
     value = new List<T>();
     lookup.Add(key, value);
}
4 голосов
/ 12 апреля 2010

ConcurrentDictionary в .NET 4.0 имеет этот приятный метод . Вы также можете написать метод расширения для этого.

3 голосов
/ 17 февраля 2012

При работе с .NET Framework 4 или более поздней версией вы можете использовать метод AddOrUpdate

dict.AddOrUpdate(key,value)  

добавить или обновить, как это

dict[key] = value;
1 голос
/ 12 апреля 2010

Я не уверен, есть ли такой метод, как вы просили, но вы можете написать для него небольшую функцию или использовать исключение try catch, предположительно, если вы попытаетесь добавить уже существующее значение, оно выдаст исключение. Если вы поймете это и проигнорируете ... Просто предложение

0 голосов
/ 25 сентября 2015

Мне нравится AddOrUpdate метод ConcurrentDictionary , но мне также нравится производительность коллекции Dictionary :) Итак, это метод расширения для всех классов, реализующих IDictionary .

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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...