There might exist dialect specific ways, or maybe a general one. I have two dictionaries, let's say:
a := {'a' -> 1} asDictionary.
b := {'b' -> 2} asDictionary.
Now I want to get c
as the union of a
and b
.
There might exist dialect specific ways, or maybe a general one. I have two dictionaries, let's say:
a := {'a' -> 1} asDictionary.
b := {'b' -> 2} asDictionary.
Now I want to get c
as the union of a
and b
.
It depends on whether you want a third object or you prefer to include, say b
, into a
.
For the first case
c := Dictionary new.
a keysAndValuesDo: [:k :v | c at: k put: v].
b keysAndValuesDo: [:k :v | c at: k put: v].
For the second
b keysAndValuesDo: [:k :v | a at: k put: v].
Note also that the operation is not commutative, meaning that if the same key occurs in both dictionaries, the one that will survive in the result is the last added.
Another one:
Dictionary new addAll: a; addAll: b; yourself
Also works when a and b are other collections of Associations, as in your question without asDictionary. Works at least in Squeak.
As pointed out by @aka.nice in the comments, depending on your Smalltalk implementation it may have the side effect of sharing the Association objects with the input dictionaries. It certainly is that way in Squeak. If a and b have common keys, it may even modify one of the input dictionaries (in Squeak a) because first an existing Association is added to the new Dictionary's hashtable, and then this Association gets the value from the other input Dictionary assigned.
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"
addAll: a associations
etc... –
Samhita a at: 'a' put: 4
will also modify c... –
Samhita a := {'c'->0} as:Dictionary. b := {'c'->7} as:Dictionary. Dictionary new addAll: a; addAll: b; yourself. ^a at: 'c'.
will answer 7 –
Samhita In Squeak/Pharo you can simply use union:
a := {'a' -> 1} as: Dictionary.
b := {'b' -> 2} as: Dictionary.
c := a union: b.
-> a Dictionary('a'->1 'b'->2 )
Note that the elements of b will be chosen in case of overlapping keys
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 )
c := a, b
works in Pharo (but not in Dolphin)
,
so far has only ever been used for sequences (SequenceableCollection) for which it is very natural. Dictionary are unordered and overlapping keys will be fused. Considering that Pharo has union:
too, that's a poor choice IMO. –
Samhita I think Leandro's and aka.nice's answer provide you with nice solutions. Both also mention that you are going to lose information when the key is same for both of the dictionaries.
I'm writing this in order to complement these answers. If you should need to keep the duplicate key -> value
I would do it the following way:
a := {'a' -> 1. 'c'->3} as: Bag.
b := {'b' -> 2. 'c'->20} as: Bag.
c := a union: b.
Which will give you a Bag with Dictionary as contents:
Dictionary('b'->2->1 'a'->1->1 'c'->20->1 'c'->3->1)
(I'm using Smalltalk/X-jv)
Here's a one-liner that should work in any Smalltalk, but might share associations:
c := (a associations, b associations) asDictionary
Next is a version that should work in any Smalltalk without risk of sharing associations,
and is what both (c := a, b) and (c := a union: b) should be doing
in all of them:
c := (a associations, b associations)
inject: Dictionary new
into: [:all :each|
all at: each key put: each value
; yourself
]
Finally, this last one should also work in any version of Smalltalk,
without risk of either sharing associations or losing any information:
c := (a associations, b associations)
inject: Dictionary new
into: [:all :each|
(all at: each key ifAbsentPut: List new)
add: each value
; yourself
]
© 2022 - 2024 — McMap. All rights reserved.