Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I merge two dictionaries in Smalltalk with a oneliner?

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.

like image 811
melkyades Avatar asked Jan 06 '21 15:01

melkyades


People also ask

Can I use two dictionaries to merge?

You can merge two dictionaries using the | operator. It is a very convenient method to merge dictionaries; however, it is only used in the python 3.9 version or more.

How do I merge two dictionaries in a single expression?

Using | in Python 3.9 In the latest update of python now we can use “|” operator to merge two dictionaries. It is a very convenient method to merge dictionaries.

Which function helps merge dictionary?

Dictionary has a method update() which merges the dictionary with the items from the other dictionary in-place and overwrites existing keys. The update method modifies the current dictionary.

How can I merge two dictionaries into one dictionary?

Say you have two dictionaries and you want to merge them into a new dictionary without altering the original dictionaries: The desired result is to get a new dictionary ( z) with the values merged, and the second dictionary's values overwriting those from the first. A new syntax for this, proposed in PEP 448 and available as of Python 3.5, is

How to unpack and merge two dictionaries in Python?

Items in Python can be unpacked using either the * or the ** characters. For dictionaries, to access both the key and value, you need to use the ** characters. Let’s see how we can use this to merge two dictionaries in Python:

Why is it important to combine dictionaries in Python?

Because of the important of retrieving web data, being able to combine dictionaries in Python is an important skill to understand. Python dictionaries use a key:value mapping to store data. Keys must be unique and must be immutable objects (such as strings or tuples).

Does [double star] affect the other two dictionaries in Python?

This does not affect the other two dictionaries. ** implies that an argument is a dictionary. Using ** [double star] is a shortcut that allows you to pass multiple arguments to a function directly using a dictionary. For more information refer **kwargs in Python.


5 Answers

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.

like image 135
Leandro Caniglia Avatar answered Oct 05 '22 16:10

Leandro Caniglia


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 )
like image 31
aka.nice Avatar answered Oct 05 '22 17:10

aka.nice


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"
like image 44
JayK Avatar answered Oct 05 '22 16:10

JayK


c := a, b works in Pharo (but not in Dolphin)

like image 27
melkyades Avatar answered Oct 05 '22 17:10

melkyades


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)

like image 21
tukan Avatar answered Oct 05 '22 18:10

tukan