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

How to add count for each unique val in list

假设我有一个列表。

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)]

您可以将 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']

您可以使用字典(或者更好的是 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']

您可以使用 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']

请注意,如果您希望字符串在 temp 中包含多个字符,则 seen.update(c) 可能会产生意想不到的结果。演示:

>>> 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']

事实上(正如 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]