Как добавить количество для каждого уникального значения в списке

Предположим, у меня есть список.

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

Ответ 1

Вы можете использовать collections.defaultdict с циклом for:

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

Ответ 2

Вы можете использовать Counter или defaultdict(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']

Ответ 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']

Ответ 4

На самом деле возможно (как ОП попросил в некоторых комментариях) сделать это с помощью простого понимания списка, без слишком большого количества нежелательных побочных эффектов. Однако я не уверен, что это хорошая идея - некоторые люди могут не найти этот код проще всего для понимания:

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]