I am using a Dictionary where the keys are strings and the values are integers. How can I get the key with the largest value out of this Dictionary?
I know there is the associationsDo: method I can use to iterate over both keys and values, but I don't know how to get the maximum value.
| countDict |
countDict := Dictionary new.
...
countDict associationsDo: [ :k :v | ??? ]
Here is a way to do it following your idea:
| max largest |
max := nil.
countDict associationsDo: [:k :v |
(max isNil or: [v > largest])
ifTrue: [
max := k.
largest := v]].
^max
Here is another way, shorter but not very efficient:
countDict isEmpty ifTrue: [^nil].
^countDict keyAtValue: countDict max
Also, if you have a countDict I suspect that it represents the number of occurrences of every key. If that is the case you shouldn't be using a Dictionary but a Bag. Instances of Bag represent collections of objects which may have several occurrences each. Examples:
names := Bag new.
people do: [:person | names add: person firstName].
and you may end up with
2 occurrences of 'John'
1 occurrence of 'Paul'
4 occurrences of 'Ringo'
7 occurrences of 'George'
names occurrencesOf: 'John' ----> 2
The Bag will internally have a countDict sort of Dictionary, but to your model a Bag could reveal better your intention than a Dictionary because you will only need to add: elements without having to count them; the Bag will do it for you.
With a Bag your computation becomes
bag occurrencesOf: bag asSet max
The reason to send asSet is to avoid iterating several times on every value, which would happen if we simply put bag max. This simpler code will also work, but given that max iterates using do: and Bag implements do: by repeating the evaluation of the block for every occurrence of the element, this solution would be less efficient.
A better approach would be to re-implement max (and min) in Bag so that each element is iterated once. This would be similar to the code that we have above which followed your initial idea (associationsDo: [...). But let's leave the details of this as an exercise for the reader.
Anyway, if we re-implemnted max in Bag, the code would become simple and efficient at once:
bag occurrencesOf: bag max
Another nice way to do this:
(countDict associations detectMax: #value) key
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With