はじめに
みずほリサーチ&テクノロジーズの@fujineです。
for
文などでイテラブルの要素を取得する際、連番のインデックスも同時に生成する方法として、組み込み関数であるenumerateがよく使用されます。
data = "abcdefg"
res = [(i, d) for i, d in enumerate(data)]
print(res)
[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd'), (4, 'e'), (5, 'f'), (6, 'g')]
このインデックスを、連番ではなくアルファベットで生成したいというのが本記事の趣旨です。なお、整数と違いアルファベットの個数は有限のため、循環的に生成する必要があります。
この方法を応用すれば、アルファベットに限らず任意のイテラブルをenumerate
のように扱うことができるようになります。
検証環境はPython3.9です。
アルファベット版のenumerate
enumerateのアルファベット版は、標準ライブラリのitertoolsとstringを使用します。
30個の連番にアルファベットを付与するコードと実行結果は以下の通りです。
import itertools
import string
index = itertools.cycle(string.ascii_uppercase)
res = [(i, x) for i, x in zip(index, range(30))]
print(res)
[('A', 0), ('B', 1), ('C', 2), ...(中略)..., ('Y', 24), ('Z', 25), ('A', 26), ('B', 27), ('C', 28), ('D', 29)]
このコードは、以下仕組みで動いています。
-
ascii_uppercaseは、英大文字(
A..Z
)の文字列 - itertools.cycleにて、イテラブルの要素を循環的に取得
- zip関数に複数のイテラブルを指定した場合、「短い方のイテラブルが先に終了した場合はzipも終了する」という特徴を活用
ascii_uppercase
をascii_letters(英小文字+英大文字)にすれば、26+26=52文字と更に長い文字群も生成できます。
アルファベット+数字を組み合わせたenumerate
次に、A0
、A1
、...、A9
、B0
、B1
、...、Z9
のように、アルファベットと数字を組み合わせたインデックスを生成してみます。
index = itertools.cycle(product(string.ascii_uppercase, string.digits))
res = [(f'{a}{n}', x) for (a, n), x in zip(index, range(30))]
print(res)
[('A0', 0), ('A1', 1), ('A2', 2), ...(中略)..., ('A9', 9), ('B0', 10), ('B1', 11), ...(中略)..., ('C9', 29)]
仕組みは、ascii_uppercase
(A..Z
の英大文字)とdigits
(0..9の数字)の2つのイテラブルを、itertools.productで組合せ生成しています。
まとめ
今回は小ネタとして、enumerateのようにアルファベットを循環生成する方法をご紹介しました。
「イテラブルの要素を順番にグルーピングしたい」というシーンで活用できれば幸いです。