4

我正在使用 python 读取文本文件,其格式设置为每列中的值可能是数字或字符串。

当这些值是字符串时,我需要分配该字符串的唯一 ID(在同一列下的所有字符串中唯一;如果相同的字符串出现在同一列下的其他位置,则必须分配相同的 ID)。

什么是有效的方法?

4

3 回答 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是一个绑定方法,它在您调用它时会生成一个新整数。

结合起来,这些工具会生成一个 dict,当您查找以前从未查找过的内容时,该 dict 会返回一个新整数。

于 2013-09-04T04:41:15.770 回答
2

为 python 3 更新了 defaultdict 答案,.next现在在哪里.__next__,并且为了 pylint 合规性,不鼓励使用“魔术”__*__方法:

ids = collections.defaultdict(functoools.partial(next, itertools.count()))
于 2013-10-09T10:06:38.610 回答
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)
于 2013-09-04T05:00:17.563 回答