Получение KeyValuePair <> непосредственно из словаря <> - PullRequest
31 голосов
/ 25 октября 2009

У меня есть System.Collections.Generic.Dictionary<A, B> dict, где A и B - классы, а экземпляр A a (где dict.ContainsKey(a) - true).

Можно ли получить KeyValuePair, содержащую a, прямо из словаря?
Или мне нужно создать новую KeyValuePair: new KeyValuePair<A, B>(a, dict[a])?

Ответы [ 4 ]

38 голосов
/ 25 октября 2009

Вам необходимо создать новый KeyValuePair 1 - но имейте в виду, что KVP в любом случае является типом значения (структурой), поэтому вы не вводите новую неэффективность, выполняя это , Любой метод, возвращающий KVP, в любом случае будет создавать копию - вы просто создаете экземпляр напрямую.

Вы всегда можете добавить метод расширения к IDictionary<TKey, TValue>, если хотите:

public static KeyValuePair<TKey, TValue> GetEntry<TKey, TValue>
    (this IDictionary<TKey, TValue> dictionary,
     TKey key)
{
    return new KeyValuePair<TKey, TValue>(key, dictionary[key]);
}

Как отмечено в комментариях, вполне возможно, что ключ, который хранится в словаре, не является тем же , как предоставленный, просто семантически равным - с помощью некоторой семантики, которая может быть настроена с помощью IEqualityComparer (как, например, в словаре без учета регистра). В этом случае приведенный выше код вернет не фактическую запись в словаре, а запись с ключом, который вы указали для поиска. К сожалению, нет эффективного способа найти исходный ключ - вам придется перебирать словарь: (


1 Я знал, что вы можете перебрать записи словаря и найти соответствующую запись таким образом, но я не вижу причин, почему вы когда-нибудь захотите сделать это, когда у вас есть совершенно хороший индексатор, который является O (1) вместо O (N).

16 голосов
/ 25 октября 2009

Поскольку Dictionary<TKey, TValue> реализует IEnumerable<KeyValuePair<TKey, TValue>>, вы можете использовать linq:

var pair = _dictionary.SingleOrDefault(p => p.Key == myKey);
1 голос
/ 06 марта 2015

Мы не можем добраться до "IPHone" таким образом:

var dict = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
               {
                   { "IPHone", "TCP/IP honing tools" }
               };

Console.WriteLine(dict["iPhone"]); // "TCP/IP honing tools"
Console.WriteLine( ??? ); // "IPHone"

Похоже, что с текущим API не существует решения O (1), но циклическая обработка всех записей работает:

var keyValue = dict.First(p => dict.Comparer.Equals(p.Key, "iPhone"));

Console.WriteLine(keyValue.Key); // "IPHone"
Console.WriteLine(keyValue.Value); // "TCP/IP honing tools"

Или как расширение для ленивых:

[Pure]
public static KeyValuePair<TKey, TValue> GetEntry<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TKey key)
{
    var comparer = dictionary.Comparer;
    return dictionary.FirstOrDefault(p => comparer.Equals(p.Key, key));
}
0 голосов
/ 17 ноября 2015

Для меня myDict.AsEnumerable делает это ...

...