我正在使用python读取文本文件,格式化每列中的值可能是数字或字符串。
当这些值是字符串时,我需要分配该字符串的唯一ID(在同一列下的所有字符串中都是唯一的;如果相同的字符串出现在同一列的其他位置,则必须分配相同的ID)。
什么是有效的方法呢?
答案 0 :(得分:12)
使用defaultdict和默认值factory生成新ID:
ids = collections.defaultdict(itertools.count().next)
ids['a'] # 0
ids['b'] # 1
ids['a'] # 0
当您在defaultdict中查找某个键时,如果它尚未存在,则defaultdict会调用用户提供的默认值factory来获取该值并在返回之前将其存储。
collections.count()
创建一个从0开始计数的迭代器,因此collections.count().next
是一个绑定方法,只要你调用它就会产生一个新的整数。
结合起来,这些工具产生一个dict,当你查找以前从未查找过的东西时,它会返回一个新的整数。
答案 1 :(得分:2)
对于python 3更新了defaultdict answer,其中.next
现在为.__next__
,对于pylint合规性,不鼓励使用“magic”__*__
方法:
ids = collections.defaultdict(functoools.partial(next, itertools.count()))
答案 2 :(得分:0)
创建一个集合,然后将字符串添加到集合中。这将确保字符串不重复;然后你可以使用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)