我正在使用 python 读取文本文件,其格式设置为每列中的值可能是数字或字符串。
当这些值是字符串时,我需要分配该字符串的唯一 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
是一个绑定方法,它在您调用它时会生成一个新整数。
结合起来,这些工具会生成一个 dict,当您查找以前从未查找过的内容时,该 dict 会返回一个新整数。
为 python 3 更新了 defaultdict 答案,.next
现在在哪里.__next__
,并且为了 pylint 合规性,不鼓励使用“魔术”__*__
方法:
ids = collections.defaultdict(functoools.partial(next, itertools.count()))
创建一个集合,然后将字符串添加到该集合。这将确保字符串不重复;然后您可以使用 enumerate 来获取每个字符串的唯一 ID。再次写出文件时使用此 ID。
在这里,我假设第二列是您要扫描文本或整数的列。
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)