如何将Smalltalk中的两个词典与一个oneliner合并



可能存在特定于方言的方式,也可能是通用的方式。我有两本字典,比方说:

a := {'a' -> 1} asDictionary.
b := {'b' -> 2} asDictionary.

现在我想得到c作为ab的并集。

这取决于您是想要第三个对象,还是希望将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
]

相关内容

最新更新