3.5 递增地更新字典

我们可以使用字典计数出现的次数,模拟fig-tally所示的计数词汇的方法。首先初始化一个空的defaultdict,然后处理文本中每个词性标记。如果标记以前没有见过,就默认计数为零。每次我们遇到一个标记,就使用+=运算符递增它的计数。

  1. >>> from collections import defaultdict
  2. >>> counts = defaultdict(int)
  3. >>> from nltk.corpus import brown
  4. >>> for (word, tag) in brown.tagged_words(categories='news', tagset='universal'):
  5. ... counts[tag] += 1
  6. ...
  7. >>> counts['NOUN']
  8. 30640
  9. >>> sorted(counts)
  10. ['ADJ', 'PRT', 'ADV', 'X', 'CONJ', 'PRON', 'VERB', '.', 'NUM', 'NOUN', 'ADP', 'DET']
  11. >>> from operator import itemgetter
  12. >>> sorted(counts.items(), key=itemgetter(1), reverse=True)
  13. [('NOUN', 30640), ('VERB', 14399), ('ADP', 12355), ('.', 11928), ...]
  14. >>> [t for t, c in sorted(counts.items(), key=itemgetter(1), reverse=True)]
  15. ['NOUN', 'VERB', 'ADP', '.', 'DET', 'ADJ', 'ADV', 'CONJ', 'PRON', 'PRT', 'NUM', 'X']

3.3中的列表演示了一个重要的按值排序一个字典的习惯用法,来按频率递减顺序显示词汇。sorted()的第一个参数是要排序的项目,它是由一个词性标记和一个频率组成的元组的列表。第二个参数使用函数itemgetter()指定排序的键。在一般情况下,itemgetter(n)返回一个函数,这个函数可以在一些其他序列对象上被调用获得这个序列的第 n 个元素,例如:

  1. >>> pair = ('NP', 8336)
  2. >>> pair[1]
  3. 8336
  4. >>> itemgetter(1)(pair)
  5. 8336

sorted()的最后一个参数指定项目是否应被按相反的顺序返回,即频率值递减。

3.3的开头还有第二个有用的习惯用法,那里我们初始化一个defaultdict,然后使用for循环来更新其值。下面是一个示意版本:

>>> my_dictionary = defaultdict(function to create default value)``>>> for item in sequence:``... my_dictionary[item_key] is updated with information about item

下面是这种模式的另一个示例,我们按它们最后两个字母索引词汇:

  1. >>> last_letters = defaultdict(list)
  2. >>> words = nltk.corpus.words.words('en')
  3. >>> for word in words:
  4. ... key = word[-2:]
  5. ... last_letters[key].append(word)
  6. ...
  7. >>> last_letters['ly']
  8. ['abactinally', 'abandonedly', 'abasedly', 'abashedly', 'abashlessly', 'abbreviately',
  9. 'abdominally', 'abhorrently', 'abidingly', 'abiogenetically', 'abiologically', ...]
  10. >>> last_letters['zy']
  11. ['blazy', 'bleezy', 'blowzy', 'boozy', 'breezy', 'bronzy', 'buzzy', 'Chazy', ...]

下面的例子使用相同的模式创建一个颠倒顺序的词字典。(你可能会试验第 3 行来弄清楚为什么这个程序能运行。)

  1. >>> anagrams = defaultdict(list)
  2. >>> for word in words:
  3. ... key = ''.join(sorted(word))
  4. ... anagrams[key].append(word)
  5. ...
  6. >>> anagrams['aeilnrt']
  7. ['entrail', 'latrine', 'ratline', 'reliant', 'retinal', 'trenail']

由于积累这样的词是如此常用的任务,NLTK 提供一个创建defaultdict(list)更方便的方式,形式为nltk.Index()

  1. >>> anagrams = nltk.Index((''.join(sorted(w)), w) for w in words)
  2. >>> anagrams['aeilnrt']
  3. ['entrail', 'latrine', 'ratline', 'reliant', 'retinal', 'trenail']

注意

nltk.Index是一个支持额外初始化的defaultdict(list)。类似地,nltk.FreqDist本质上是一个额外支持初始化的defaultdict(int)(附带排序和绘图方法)。