web-dev-qa-db-ja.com

リスト内の一意の値ごとにカウントを追加する方法

私がリストを持っていると仮定します。

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

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

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

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']
_
11
timgeb

辞書を使用できます(または、さらに良いことに、 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
Eugene Yarmash

実際、(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]
4
psmears