• 3.5 递增地更新字典

    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)(附带排序和绘图方法)。