我有一对带有单词对的列表,想在id上描述单词。编号应介于0到len(set(words))之间。现在,列表如下所示:
[['pluripotent', 'Scharte'],
['Halswirbel', 'präventiv'],
['Kleiber', 'Blauspecht'],
['Kleiber', 'Scheidung'],
['Nillenlutscher', 'Salzstangenlecker']]
结果应具有相同的格式,但应使用ID。例如:
[[0, 1],
[2, 3],
[4, 5],
[4, 6],
[7, 8]]
到目前为止,我已经有了这个,但是它没有给我正确的输出:
def words_to_ids(labels):
vocabulary = []
word_to_id = {}
ids = []
for word1,word2 in labels:
vocabulary.append(word1)
vocabulary.append(word2)
for i, word in enumerate(vocabulary):
word_to_id [word] = i
for word1,word2 in labels:
ids.append([word_to_id [word1], word_to_id [word1]])
print(ids)
输出:
[[0, 0], [2, 2], [6, 6], [6, 6], [8, 8]]
在有唯一单词的地方重复ID。
答案 0 :(得分:2)
您有两个错误。首先,您在这里有一个简单的错字:
for word1,word2 in labels:
ids.append([word_to_id [word1], word_to_id [word1]])
您要在此添加word1
两次的ID。更正第二个word1
来查找word2
。
接下来,您不会测试您是否曾经看过一个单词,因此对于'Kleiber'
,您首先为其指定ID 4
,然后在下一次迭代时使用6
覆盖该条目。您需要提供唯一单词编号,而不是所有单词:
counter = 0
for word in vocabulary:
if word not in word_to_id:
word_to_id[word] = counter
counter += 1
,或者如果您已经列出该单词,则根本无法在vocabulary
中添加一个单词。顺便说一下,您在这里实际上不需要单独的vocabulary
列表。单独的循环不会为您带来任何好处,因此以下方法也可以:
word_to_id = {}
counter = 0
for words in labels:
for word in words:
word_to_id [word] = counter
counter += 1
通过使用defaultdict
object和itertools.count()
提供默认值,可以大大简化代码:
from collections import defaultdict
from itertools import count
def words_to_ids(labels):
word_ids = defaultdict(count().__next__)
return [[word_ids[w1], word_ids[w2]] for w1, w2 in labels]
每次调用count()
时,__next__
对象都会为您提供序列中的下一个整数值,并且每次您尝试访问未访问的键时,defaultdict()
都会调用该整数值。尚未存在于字典中。它们共同确保了每个唯一单词的唯一ID。
答案 1 :(得分:1)
有两个问题:
word1
中重复搜索word_to_id
来打错了字。word_to_id
字典时,您只需要考虑唯一值即可。例如,在Python 3.7+中,您可以利用插入顺序字典:
for i, word in enumerate(dict.fromkeys(vocabulary)):
word_to_id[word] = i
for word1, word2 in labels:
ids.append([word_to_id[word1], word_to_id[word2]])
3.7版之前的替代方法是使用collections.OrderedDict
或itertools
unique_everseen
recipe。
如果没有订购要求,则只需使用set(vocabulary)
。