从 Smalltalk 中的字典中获取具有最大值的键

Get key with largest value from a dictionary in Smalltalk

我正在使用字典,其中键是字符串,值是整数。我怎样才能从这个字典中得到具有最大值的键?

我知道可以使用 associationsDo: 方法来遍历键和值,但我不知道如何获得最大值。

| countDict |
countDict := Dictionary new.
...
countDict associationsDo: [ :k :v | ??? ]

这里有一种方法可以按照您的想法进行:

| max largest |
max := nil.
countDict associationsDo: [:k :v |
  (max isNil or: [v > largest])
    ifTrue: [
      max := k.
      largest := v]].
^max

这是另一种方式,更短但效率不高:

 countDict isEmpty ifTrue: [^nil].
 ^countDict keyAtValue: countDict max

此外,如果您有一个 countDict,我怀疑它代表每个键出现的次数。如果是这种情况,您不应该使用 Dictionary,而应使用 BagBag 的实例表示对象的集合,每个对象可能有多次出现。示例:

names := Bag new.
people do: [:person | names add: person firstName].

你可能会得到

2 occurrences of 'John'
1 occurrence of 'Paul'
4 occurrences of 'Ringo'
7 occurrences of 'George'

names occurrencesOf: 'John'  ---->  2

Bag 内部会有 countDict 之类的 Dictionary,但对于您的模型来说,BagDictionary 更能揭示您的意图因为您只需要 add: 个元素而无需计算它们; Bag 会为您完成。

有了 Bag 你的计算就变成了

bag occurrencesOf: bag asSet max

发送asSet的原因是为了避免在每个值上迭代多次,如果我们简单地输入bag max就会发生这种情况。这个更简单的代码也可以工作,但是考虑到 max 使用 do: 迭代并且 Bag 通过对元素的每次出现重复块的评估来实现 do:,这个解决方案效率会降低。

更好的方法是在 Bag 中重新实现 max(和 min),以便每个元素迭代一次。这类似于我们上面的代码,它遵循您最初的想法 (associationsDo: [...)。但是,让我们将此细节留作 reader.

的练习。

无论如何,如果我们在Bag中重新实现max,代码会立刻变得简单高效:

 bag occurrencesOf: bag max

另一个很好的方法:

(countDict associations detectMax: #value) key