获取KeyValuePair<>直接来自字典<>

时间:2009-10-24 20:59:02

标签: c# .net generics collections dictionary

我有System.Collections.Generic.Dictionary<A, B> dict,其中A和B是类,实例A a(其中dict.ContainsKey(a)为真)。

是否可以直接从字典中获取包含a的KeyValuePair?
或者我是否需要创建一个新的KeyValuePair:new KeyValuePair<A, B>(a, dict[a])

5 个答案:

答案 0 :(得分:38)

你需要创建一个新的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]);
}

正如评论中所指出的那样,存储在字典中的密钥完全有可能与提供的密钥不是相同,只是在语义上相同 - 通过某些语义可以由{ {1}}(例如,与不区分大小写的字典一样。)在这种情况下,上面的代码不会返回字典中的实际条目,而是返回您提供的用于查找的键的条目。不幸的是,没有找到原始密钥的有效方法 - 你必须遍历字典:(


1 我知道你可以迭代字典条目并找到相应的条目,但我没有理由为什么你想要这样做一个非常好的索引器,它是O(1)而不是O(N)。

答案 1 :(得分:16)

Dictionary<TKey, TValue>实现IEnumerable<KeyValuePair<TKey, TValue>>时,您可以使用linq:

var pair = _dictionary.SingleOrDefault(p => p.Key == myKey);

答案 2 :(得分:1)

我们无法以"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));
}

答案 3 :(得分:0)

对我来说myDict.AsEnumerable做到了......

答案 4 :(得分:0)

接受的答案可能对某些常见情况没有太大帮助。请记住,关键是一个类。因此,为了访问该键的值对象,必须已经存在一个键对象。那么,如果您有一个较旧的键对象并且字典在该键对象中包含较新的信息(但仍使用该键对象中的相同键字段)怎么办?或者,另一种非常合理的情况是,如果只有用作键的字段可用,然后创建一个包含这些键字段的临时键对象会怎样?

接受的答案使用扩展方法返回包含旧键的 KeyValuePair,而不是字典中的实际键对象。因此,它不适用于这些常见情况。

因此,Supercat 对包含键的值使用 KeyValuePair 的想法是唯一可以在 O(1) 时间内工作的方法。缺点是这种方法不仅更复杂,而且对于字典中的每个条目还需要额外的 8 个字节(对于 64 位操作系统),这通常不是问题。看起来微软错过了这个机会,因为他们真的应该提供一种返回字典中键的方法。

以下是如何创建以 KeyValuePair 作为值的字典的示例:

    var dict = new Dictionary<a, KeyValuePair<a, b>>();

然后访问它:

    var kvp = dict[key]; // key is of type a.
    a itemKey = kvp.key;
    b itemVal = kvp.value;

因此,如果您可以控制字典定义,这样的代码将起作用。如果您使用的是 3rd 方软件,或者更改太麻烦,那么您必须遍历整个集合 - 这是一个 O(n) 操作。