3.5 递增地更新字典
我们可以使用字典计数出现的次数,模拟fig-tally所示的计数词汇的方法。首先初始化一个空的defaultdict
,然后处理文本中每个词性标记。如果标记以前没有见过,就默认计数为零。每次我们遇到一个标记,就使用+=
运算符递增它的计数。
>>> from collections import defaultdict
>>> counts = defaultdict(int)
>>> from nltk.corpus import brown
>>> for (word, tag) in brown.tagged_words(categories='news', tagset='universal'):
... counts[tag] += 1
...
>>> counts['NOUN']
30640
>>> sorted(counts)
['ADJ', 'PRT', 'ADV', 'X', 'CONJ', 'PRON', 'VERB', '.', 'NUM', 'NOUN', 'ADP', 'DET']
>>> from operator import itemgetter
>>> sorted(counts.items(), key=itemgetter(1), reverse=True)
[('NOUN', 30640), ('VERB', 14399), ('ADP', 12355), ('.', 11928), ...]
>>> [t for t, c in sorted(counts.items(), key=itemgetter(1), reverse=True)]
['NOUN', 'VERB', 'ADP', '.', 'DET', 'ADJ', 'ADV', 'CONJ', 'PRON', 'PRT', 'NUM', 'X']
3.3中的列表演示了一个重要的按值排序一个字典的习惯用法,来按频率递减顺序显示词汇。sorted()
的第一个参数是要排序的项目,它是由一个词性标记和一个频率组成的元组的列表。第二个参数使用函数itemgetter()
指定排序的键。在一般情况下,itemgetter(n)
返回一个函数,这个函数可以在一些其他序列对象上被调用获得这个序列的第 n 个元素,例如:
>>> pair = ('NP', 8336)
>>> pair[1]
8336
>>> itemgetter(1)(pair)
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
下面是这种模式的另一个示例,我们按它们最后两个字母索引词汇:
>>> last_letters = defaultdict(list)
>>> words = nltk.corpus.words.words('en')
>>> for word in words:
... key = word[-2:]
... last_letters[key].append(word)
...
>>> last_letters['ly']
['abactinally', 'abandonedly', 'abasedly', 'abashedly', 'abashlessly', 'abbreviately',
'abdominally', 'abhorrently', 'abidingly', 'abiogenetically', 'abiologically', ...]
>>> last_letters['zy']
['blazy', 'bleezy', 'blowzy', 'boozy', 'breezy', 'bronzy', 'buzzy', 'Chazy', ...]
下面的例子使用相同的模式创建一个颠倒顺序的词字典。(你可能会试验第 3 行来弄清楚为什么这个程序能运行。)
>>> anagrams = defaultdict(list)
>>> for word in words:
... key = ''.join(sorted(word))
... anagrams[key].append(word)
...
>>> anagrams['aeilnrt']
['entrail', 'latrine', 'ratline', 'reliant', 'retinal', 'trenail']
由于积累这样的词是如此常用的任务,NLTK 提供一个创建defaultdict(list)
更方便的方式,形式为nltk.Index()
。
>>> anagrams = nltk.Index((''.join(sorted(w)), w) for w in words)
>>> anagrams['aeilnrt']
['entrail', 'latrine', 'ratline', 'reliant', 'retinal', 'trenail']
注意
nltk.Index
是一个支持额外初始化的defaultdict(list)
。类似地,nltk.FreqDist
本质上是一个额外支持初始化的defaultdict(int)
(附带排序和绘图方法)。