- 3.1 索引列表 VS 字典
3.1 索引列表 VS 字典
我们已经看到,文本在 Python 中被视为一个词列表。链表的一个重要的属性是我们可以通过给出其索引来“看”特定项目,例如text1[100]。请注意我们如何指定一个数字,然后取回一个词。我们可以把链表看作一种简单的表格,如3.1所示。

图 3.1:列表查找:一个整数索引帮助我们访问 Python 列表的内容。
对比这种情况与频率分布(3),在那里我们指定一个词然后取回一个数字,如fdist['monstrous'],它告诉我们一个给定的词在文本中出现的次数。用词查询对任何使用过字典的人都很熟悉。3.2展示一些更多的例子。

图 3.2:字典查询:我们使用一个关键字,如某人的名字、一个域名或一个英文单词,访问一个字典的条目;字典的其他名字有映射、哈希表、哈希和关联数组。
在电话簿中,我们用名字查找一个条目得到一个数字。当我们在浏览器中输入一个域名,计算机查找它得到一个 IP 地址。一个词频表允许我们查一个词找出它在一个文本集合中的频率。在所有这些情况中,我们都是从名称映射到数字,而不是其他如列表那样的方式。总之,我们希望能够在任意类型的信息之间映射。3.1列出了各种语言学对象以及它们的映射。
表 3.1:
语言学对象从键到值的映射
>>> pos = {}>>> pos{}>>> pos['colorless'] = 'ADJ' ![[1]](/projects/nlp-py-2e-zh/Images/7a979f968bd33428b02cde62eaf2b615.jpg)>>> pos{'colorless': 'ADJ'}>>> pos['ideas'] = 'N'>>> pos['sleep'] = 'V'>>> pos['furiously'] = 'ADV'>>> pos ![[2]](/projects/nlp-py-2e-zh/Images/6ac827d2d00b6ebf8bbc704f430af896.jpg){'furiously': 'ADV', 'ideas': 'N', 'colorless': 'ADJ', 'sleep': 'V'}
所以,例如,
说的是 colorless 的词性是形容词,或者更具体地说:在字典pos中,键'colorless'被分配了值'ADJ'。当我们检查pos的值时
,我们看到一个键-值对的集合。一旦我们以这样的方式填充了字典,就可以使用键来检索值:
>>> pos['ideas']'N'>>> pos['colorless']'ADJ'
当然,我们可能会无意中使用一个尚未分配值的键。
>>> pos['green']Traceback (most recent call last):File "<stdin>", line 1, in ?KeyError: 'green'
这就提出了一个重要的问题。与列表和字符串不同,我们可以用len()算出哪些整数是合法索引,我们如何算出一个字典的合法键?如果字典不是太大,我们可以简单地通过查看变量pos检查它的内容。正如在前面(
行)所看到,这为我们提供了键-值对。请注意它们的顺序与最初放入它们的顺序不同;这是因为字典不是序列而是映射(参见3.2),键没有固定地排序。
换种方式,要找到键,我们可以将字典转换成一个列表
——要么在期望列表的上下文中使用字典,如作为sorted()的参数
,要么在for 循环中
。
>>> list(pos) ![[1]](/projects/nlp-py-2e-zh/Images/7a979f968bd33428b02cde62eaf2b615.jpg)['ideas', 'furiously', 'colorless', 'sleep']>>> sorted(pos) ![[2]](/projects/nlp-py-2e-zh/Images/6ac827d2d00b6ebf8bbc704f430af896.jpg)['colorless', 'furiously', 'ideas', 'sleep']>>> [w for w in pos if w.endswith('s')] ![[3]](/projects/nlp-py-2e-zh/Images/934b688727805b37f2404f7497c52027.jpg)['colorless', 'ideas']
注意
当你输入list(pos)时,你看到的可能会与这里显示的顺序不同。如果你想看到有序的键,只需要对它们进行排序。
与使用一个for循环遍历字典中的所有键一样,我们可以使用for循环输出列表:
>>> for word in sorted(pos):... print(word + ":", pos[word])...colorless: ADJfuriously: ADVsleep: Videas: N
最后,字典的方法keys()、values()和items()允许我们以单独的列表访问键、值以及键-值对。我们甚至可以排序元组
,按它们的第一个元素排序(如果第一个元素相同,就使用它们的第二个元素)。
>>> list(pos.keys())['colorless', 'furiously', 'sleep', 'ideas']>>> list(pos.values())['ADJ', 'ADV', 'V', 'N']>>> list(pos.items())[('colorless', 'ADJ'), ('furiously', 'ADV'), ('sleep', 'V'), ('ideas', 'N')]>>> for key, val in sorted(pos.items()): ![[1]](/projects/nlp-py-2e-zh/Images/7a979f968bd33428b02cde62eaf2b615.jpg)... print(key + ":", val)...colorless: ADJfuriously: ADVideas: Nsleep: V
我们要确保当我们在字典中查找某词时,一个键只得到一个值。现在假设我们试图用字典来存储可同时作为动词和名词的词 sleep:
>>> pos['sleep'] = 'V'>>> pos['sleep']'V'>>> pos['sleep'] = 'N'>>> pos['sleep']'N'
最初,pos['sleep']给的值是'V'。但是,它立即被一个新值'N'覆盖。换句话说,字典中只能有'sleep'的一个条目。然而,有一个方法可以在该项目中存储多个值:我们使用一个列表值,例如pos['sleep'] = ['N', 'V']。事实上,这就是我们在4中看到的 CMU 发音字典,它为一个词存储多个发音。
