如何为列表中的每个唯一值添加计数

时间:2018-11-01 09:49:12

标签: python string list counter

假设我有一个列表。

temp = ['A', 'B', 'A', 'B', 'A', 'B']

我正在寻找一种连接内部字符串计数的方法。

预期输出:

['A_1', 'B_1', 'A_2', 'B_2', 'A_3', 'B_3']

我能够通过使用列表理解来解决它,但是我正在寻找一种无需指定列表[1, 1, 2, 2, 3, 3]的方法。有可能吗?

[j + "_" + str(i) for i, j in zip([1, 1, 2, 2, 3, 3], temp)]

4 个答案:

答案 0 :(得分:27)

您可以将collections.defaultdictfor循环一起使用:

from collections import defaultdict

L = ['A', 'B', 'A', 'B', 'A', 'B']

dd = defaultdict(int)

res = []
for item in L:
    dd[item] += 1
    res.append(f'{item}_{dd[item]}')

print(res)

['A_1', 'B_1', 'A_2', 'B_2', 'A_3', 'B_3']

答案 1 :(得分:11)

您可以使用Counterdefaultdict(int)来跟踪遇到角色时看到该角色的次数。

>>> from collections import Counter
>>> 
>>> temp = ['A', 'B', 'A', 'B', 'A', 'B']
>>> seen = Counter()
>>> 
>>> result = []
>>> for c in temp:
...:    seen.update(c)
...:    result.append('{}_{}'.format(c, seen[c]))
...:    
>>> result
>>> ['A_1', 'B_1', 'A_2', 'B_2', 'A_3', 'B_3']

请注意,如果您期望seen.update(c)中的字符串包含多个字符,那么temp可能会产生意外结果。演示:

>>> seen = Counter()
>>> seen.update('ABC')
>>> seen
>>> Counter({'A': 1, 'B': 1, 'C': 1})

根据您希望的计数方式和期望的数据类型,您可能需要使用行

seen[c] += 1

代替

seen.update(c)

或者,没有任何导入:

>>> seen = {}
>>> result = []
>>> 
>>> for c in temp:
...:    seen[c] = seen.get(c, 0) + 1
...:    result.append('{}_{}'.format(c, seen[c]))
...:    
>>> result
>>> ['A_1', 'B_1', 'A_2', 'B_2', 'A_3', 'B_3']

答案 2 :(得分:4)

您可以使用字典(或更好的collections.defaultdict)来维护每个项目的计数:

from collections import defaultdict

lst = ['A', 'B', 'A', 'B', 'A', 'B']
lst2 = []
d = defaultdict(int)

for item in lst:
    d[item] += 1
    lst2.append('{}_{}'.format(item, d[item]))

print(lst2)  # ['A_1', 'B_1', 'A_2', 'B_2', 'A_3', 'B_3']

要在此处使用列表推导,您需要某种方式在迭代原始列表时更新每个项目的状态(即计数器)。为此,您可以使用带有默认参数的函数,例如:

def get_count(item, d=defaultdict(int)):
    d[item] += 1
    return '{}_{}'.format(item, d[item])

lst2 = [get_count(item) for item in lst]
print(lst2)  # ['A_1', 'B_1', 'A_2', 'B_2', 'A_3', 'B_3']

答案 3 :(得分:4)

实际上(如OP在某些评论中所要求的)仅通过列表理解即可完成此操作,而不会产生过多的不良副作用。我不确定这是否一定是个好主意-有些人可能找不到它最容易理解的代码:

from collections import defaultdict
import itertools

temp = ['A', 'B', 'A', 'B', 'A', 'B']

result = [j + "_" + str(next(c[j]))
          for c in [defaultdict(itertools.count)]
          for j in temp]