获取字典项作为KeyValuePair

3

对我来说,很明显字典应该有一个通过 Key 获取项目的方法。 要么我瞎了,要么...... 然而,我有以下情况:

我需要一个 Dictionary(Of Integer, k/v)。 我已经在一个 Dictionary 中拥有了 k/v,我想通过 Key 将它们添加到我的新字典中,例如:

'Dict1 has {("Key1", 123), ("Key2", 345)}
Dim dict2 As New Dictionary (Of Integer, KeyValuePair(Of String, Double))
dict2.Add(0,***dict1.GetItem("Key1")***)

当然,我可以编写一个扩展程序,而且也许我必须这样做,但是只有我错过了这个功能吗?如果有内置的方法我没有注意到,请指出来!
提前感谢,
丹尼尔
编辑:
dict1 = {(0, "apples"), (1, "oranges"), (2, "bananas")}
dict2 = {("oranges", 456), ("apples", 123), ("bananas", 789)}

新字典是按照dict1排序的有序dict2:
dictnew = {("apples", 123), ("oranges", 456), ("bananas", 789)}

所以我的方法是:
dicttemp = {(0, ("apples", 123)), (1, ("oranges", 456)), (2, ("bananas", 789))}'. `dicttemp` is a `SortedDictionary`.

接下来,我获取dicttemp的值并将其转换为Dictionary

你想从第一个字典构建第二个字典吗?新字典的键是第一个字典的索引,值是它的KeyValuePair。 - Tim Schmelter
不,新的键来自不同的来源。无论如何,我更新了我的问题以澄清整个任务 :) 通常我只是想知道为什么我不能直接访问字典项... - dba
2个回答

4

您正在查找字典的索引器。

请参考此链接

Dim a As Double = dict1("Key1")

在某些评论中,楼主说:

我需要将整个项目作为k/v添加到dict2中,并将dict1的项目添加到dict2中!!!

由于字典实现了IEnumerable(Of T),其中TKeyValuePair(Of TKey, TValue),因此您可以使用Single(...) LINQ扩展方法通过键找到一个键值对:

Dim pair As KeyValuePair(Of String, Double) = dict1.Single(Function(item) item.Key = "key")

由于字典的Add方法有一种重载形式,可以接受一个键值对作为参数。因此,我认为将dict1中的键值对添加到dict2中只需在第二个字典中调用Add方法并提供从第一个字典中获取的键值对即可:

dict2.Add(pair);

这将返回字典项的值... 我需要整个k/v项,并将dict1的项添加到dict2中!!! - dba
谢谢你的回答,我之前不知道LINQ-Method。无论如何,我刚刚实现了一个字典扩展,因此我简化了k/v对的内联调用(因为这是在循环中...)。 - dba
@dba 我认为简化 Single 是没有意义的,我理解你想要在那个循环中摆脱 lambda 和闭包... 但这只是需要习惯它! - Matías Fidemraizer
没有在扩展中使用“Single”。而是使用for each循环并测试键。据我所知,lambda在基础上工作类似...可能是错的 :) 感谢答案! - dba
@dba 嗯,Lambda表达式只是一种表达式。但是如果你指出LINQ只是一堆专门的for-each语句隐藏在美丽的语法糖后面,那么你是对的:D 你也可以使用SingleOrDefault,这样如果键不存在,它将返回字典值类型的null或默认值。 - Matías Fidemraizer

0

所以你已经有了键,唯一缺失的部分是值。因此你使用索引器或TryGetValue。然后你就有了两个部分,可以将它们添加到其他字典中。

Dim dict1 As New Dictionary(Of String, Double) From {{"Key1", 123}, {"Key2", 345}}
Dim dict2 As New Dictionary(Of Integer, KeyValuePair(Of String, Double))
Dim keyVal = New KeyValuePair(Of String, Double)("Key1", dict1("Key1"))
dict2.Add(0, keyVal)

这是 TryGetValue 的方法:
Dim d As Double
If dict1.TryGetValue("Key1", d) Then
    dict2.Add(0, New KeyValuePair(Of String, Double)("Key1", d))
End If

为了完整起见,您可以使用LINQ,尽管这样做会很慢且毫无意义:
Dim keyVal = dict1.FirstOrDefault(Function(kv)kv.Key = "Key1")

现在你正在使用类似于集合的字典,这与该类的目的相违背。实际上,这会循环所有项目,直到找到具有给定键的项目。


值得一提的是,既然您要求一个返回给定键的 KeyValuePair 的方法。这里是一个扩展方法:

<Extension()>
Public Function TryGetKeyValue(Of TKey, TValue)(dictionary As Dictionary(Of TKey, TValue), key As TKey) As KeyValuePair(Of TKey, TValue)?
    Dim value As TValue
    If dictionary.TryGetValue(key, value) Then
        Return New KeyValuePair(Of TKey, TValue)(key, value)
    End If
    Return Nothing
End Function

你可以这样使用它:

Dim keyVal As KeyValuePair(Of String, Double)? = dict1.TryGetKeyValue("Key1")
If keyVal.HasValue Then dict2.Add(0, keyVal.Value)

这是一个O(1)操作,因此比使用LINQ更高效。


嗨,我知道如何解决这个问题,但我的问题是是否有内置的方法可以做到这一点。:) 无论如何,谢谢! - dba
@dba:不,你可以使用 dic1.FirstOrDefault(Function(kv)kv.Key="Key1"),但那非常慢且毫无意义。我已将其添加到答案中,尽管我强烈建议不要这样做。 - Tim Schmelter
@dba:关键是这不是一个解决方法,因为你已经有了键,只是在寻找值。因此,没有内置的方法支持按给定键进行O(1)查找性能并返回KeyValuePair - Tim Schmelter
重点是我不是在寻找值,而是通过键来查找keyvaluepair的项 :) 我想避免在运行时定义新的KeyvaluePairs... 这是主要问题... 通过定义临时变量并将它们填充信息只是为了“匿名”添加它们对我来说是一种解决方法 :) - dba
@dba:由于 KeyValuePair(Of TKey, TValue) 是值类型(Structure),所以无论如何你都会创建新的对象(Object.ReferenceEquals 总是返回 false),即使你使用 dict2.Add(0, dict1.First())。顺便说一下:有序字典也违背了这个类的目的;-) - Tim Schmelter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接