可能存在特定于方言的方式,也可能是通用的方式。我有两本字典,比方说:
a := {'a' -> 1} asDictionary.
b := {'b' -> 2} asDictionary.
现在我想得到c
作为a
和b
的并集。
这取决于您是想要第三个对象,还是希望将b
包括在a
中。
对于第一种情况
c := Dictionary new.
a keysAndValuesDo: [:k :v | c at: k put: v].
b keysAndValuesDo: [:k :v | c at: k put: v].
对于第二个
b keysAndValuesDo: [:k :v | a at: k put: v].
还要注意,该操作是不可交换的,这意味着如果两个字典中都出现了相同的键,那么在结果中幸存的键就是最后添加的键。
在Squeak/Pharo中,您可以简单地使用union:
a := {'a' -> 1} as: Dictionary.
b := {'b' -> 2} as: Dictionary.
c := a union: b.
-> a Dictionary('a'->1 'b'->2 )
注意,在密钥重叠的情况下,将选择b的元素
a := {'a' -> 1. 'c'->0} as:Dictionary.
b := {'b' -> 2. 'c'->7} as:Dictionary.
c := a union: b.
-> a Dictionary('a'->1 'b'->2 'c'->7 )
另一个:
Dictionary new addAll: a; addAll: b; yourself
当a和b是Associations的其他集合时也适用,如您在没有asDictionary的情况下提出的问题。至少在Squeak中有效。
正如@aka.nice在评论中指出的那样,根据您的Smalltalk实现,它可能会产生与输入字典共享Association对象的副作用。在《吱吱》中肯定是这样的。如果a和b有公共键,它甚至可以修改其中一个输入字典(在Squeak a中(,因为首先将现有的关联添加到新字典的哈希表中,然后该关联从分配的另一个输入词典中获取值。
a := Dictionary newFrom: {#a -> 1}.
b := Dictionary newFrom: {#a -> 2}.
c := Dictionary new addAll: a; addAll: b; yourself.
{a at: #a. b at: #a. c at: #a} "==> #(2 2 2) in Squeak"
c := a, b
适用于Pharo(但不适用于Dolphin(
我认为Leandro和aka.nice的回答为您提供了很好的解决方案。两者都提到,当两个字典的关键字相同时,您将丢失信息。
我写这篇文章是为了补充这些答案。如果你需要保留重复的key -> value
,我会按照以下方式进行:
a := {'a' -> 1. 'c'->3} as: Bag.
b := {'b' -> 2. 'c'->20} as: Bag.
c := a union: b.
它会给你一个包,里面有字典:
Dictionary('b'->2->1 'a'->1->1 'c'->20->1 'c'->3->1)
(我使用的是Smalltalk/X-jv(
这里有一个单行线应该在任何Smalltalk中都可以工作,但可能共享关联:
c := (a associations, b associations) asDictionary
接下来是一个版本,它应该在任何Smalltalk中工作,而没有共享关联的风险,
,这就是(c:=a,b(和(c:=a union:b(都应该做的在所有这些中:
c := (a associations, b associations)
inject: Dictionary new
into: [:all :each|
all at: each key put: each value
; yourself
]
最后,最后一个也应该适用于Smalltalk的任何版本,
没有共享关联或丢失任何信息的风险:
c := (a associations, b associations)
inject: Dictionary new
into: [:all :each|
(all at: each key ifAbsentPut: List new)
add: each value
; yourself
]