我正在用Python读取一个文本文件,其中每列值可能是数字或字符串。
当这些值为字符串时,我需要为该字符串分配一个唯一的ID(在同一列下所有字符串之间唯一;如果相同的字符串在同一列下出现,则必须分配相同的ID)。
有什么高效的方法可以做到这一点?
当这些值为字符串时,我需要为该字符串分配一个唯一的ID(在同一列下所有字符串之间唯一;如果相同的字符串在同一列下出现,则必须分配相同的ID)。
有什么高效的方法可以做到这一点?
使用具有默认值工厂的defaultdict生成新的id:
ids = collections.defaultdict(itertools.count().next)
ids['a'] # 0
ids['b'] # 1
ids['a'] # 0
当您在defaultdict中查找一个键时,如果该键不存在,defaultdict会调用用户提供的默认值工厂来获取该值并将其存储后返回。
collections.count()
创建一个从0开始的迭代器,因此collections.count().next
是一个绑定方法,每次调用它时都会产生一个新的整数。
结合使用这些工具可以产生一个字典,当您查找以前未查找过的内容时,它会返回一个新的整数。
对于Python 3,defaultdict答案已更新,其中.next
现在是.__next__
,并且为了符合pylint的规范,不鼓励使用“神奇”的__*__
方法:
ids = collections.defaultdict(functoools.partial(next, itertools.count()))
seen = set()
with open('somefile.txt') as f:
reader = csv.reader(f, delimiter=',')
for row in reader:
try:
int(row[1])
except ValueError:
seen.add(row[1]) # adds string to set
# print the unique ids for each string
for id,text in enumerate(seen):
print("{}: {}".format(id, text))
现在,您可以采用相同的逻辑,并将其复制到文件的每一列。如果您预先知道列长度,则可以拥有一组列表。假设该文件有三列:
unique_strings = [set(), set(), set()]
with open('file.txt') as f:
reader = csv.reader(f, delimiter=',')
for row in reader:
for column,value in enumerate(row):
try:
int(value)
except ValueError:
# It is not an integer, so it must be
# a string
unique_strings[column].add(value)