在Python中为ID分配字符串

4
我正在用Python读取一个文本文件,其中每列值可能是数字或字符串。
当这些值为字符串时,我需要为该字符串分配一个唯一的ID(在同一列下所有字符串之间唯一;如果相同的字符串在同一列下出现,则必须分配相同的ID)。
有什么高效的方法可以做到这一点?
3个回答

12

使用具有默认值工厂的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是一个绑定方法,每次调用它时都会产生一个新的整数。

结合使用这些工具可以产生一个字典,当您查找以前未查找过的内容时,它会返回一个新的整数。


这应该正好满足他的需求。如果他正在迭代数据行,每个唯一值都通过简单插入获得唯一整数。重复检查已内置。 - g.d.d.c
他要求仅为字符串赋值而不是每一列:“当这些值是字符串时,我需要为该字符串分配一个唯一的ID(在同一列下所有字符串中唯一;如果相同的字符串在同一列的其他位置出现,则必须分配相同的ID)”。他可以通过枚举文件来获得运行计数器。 - Burhan Khalid
你仍然没有解决这个问题。如果同一字符串出现在两列中,它需要不同的id。你有一个解决方案(非常整洁,顺便说一句),但它没有解决他的问题。 - Burhan Khalid
@user2357112 非常棒。请将这个解释添加到您的答案中。我会点赞 :) - thefourtheye
@thefourtheye:在答案中添加了解释。 - user2357112
显示剩余8条评论

2

对于Python 3,defaultdict答案已更新,其中.next现在是.__next__,并且为了符合pylint的规范,不鼓励使用“神奇”的__*__方法:

ids = collections.defaultdict(functoools.partial(next, itertools.count()))

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)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接