25: enumlate関数を使って各要素のインデックスと値を取得して反復処理中に利用する

前回の続きです。

enumlate関数を使って各要素とインデックスを取得したいと思います。以前軽く触れましたが、ここで詳しく解説します。

enumlateは、引数にイテラブルを渡すと、番号と値のタプルを返す関数です。

例えばcountriesというリストがあったときに、Indiaは何番目、USAは何番目みたいな、そういう何番目という数値を取得したい場合にenumlateを使います。

enumlateを使わずに番号を表示する

まずはenumlateを使わないでやってみます。

countries = ["India", "USA", "UK", "Canada", "Australia"]
num = 0
for country in countries:
    print(num, country)
    num += 1

countriesから要素である国名とともに、番号も表示させたい。

このときenumlateを使わない場合、カウント用のnum=0から始めて、ループ中にnumを+=1します。これは原始的なやり方です。

emumlateを使って番号を表示する

一方、以下のようにenumlateを使うとnumやループ中の += 1 が不要になります。enumlateはインデックスとイテラブルの要素を返します。

countries = ["India", "USA", "UK", "Canada", "Australia"]
for num, country in enumerate(countries):
    print(num, country)

このenumlateは最初、0とIndiaを返します。次のループでは、1とUSAを返します。このようにループしていきます。

このenumlate関数はしばしば使うことがありますので覚えておきましょう。

辞書型に対してenumlateを使う

 リストの次は辞書でやってみましょう。

country_dict = {
    "India": "New Delhi",
    "USA": "Washington DC",
    "UK": "London",
    "Canada": "Ottawa",
    "Australia": "Canberra"
}
for num, city in enumerate(country_dict.items()):
    print(num, city)

国名と都市名、さらにインデックスを同時に表示したい場合どうしたらいいでしょうか?

まず、enumlate()の中はcountry_dict.items()とします。

返ってくる値を確認します。番号とタプルですね。

0 ('India', 'New Delhi')
1 ('USA', 'Washington DC')
2 ('UK', 'London')
3 ('Canada', 'Ottawa')
4 ('Australia', 'Canberra')

cityの中にはタプルが入っています。タプルの中身は、国と都市の名前が入ったタプルです。

次は、このタプルを分解して都市名だけ取り出すということをやります。なお、このタプルの中身を分解するというのをアンパッキングなんて言います。

話を戻し、このタプルをアンパッキングするにはどのようにするか?

for num, city, city in enumerate(country_dict.items()): print(num, city)

上記のようにすればいいように思うかもしれませんが、これではエラーになります。

Traceback (most recent call last): File "/Users/hoge/Library/Application Support/JetBrains/PyCharm2024.1/scratches/scratch.py", line 9, in <module> for num, city, city in enumerate(country_dict.items()): ^^^^^^^^^^^^^^^
ValueError: not enough values to unpack (expected 3, got 2)

ValueErrorということで、アンパックできませんみたいなことを言われます。ではどうすればいいか? 以下のように (country, city) を括弧で囲みます。

for num, (country, city) in enumerate(country_dict.items()):

すると、このnumで番号を受け取り、アンパッキングされたキーとバリュー、つまり国名と都市名をこの括弧の中で受け取ることができます。

country_dict = {
    "India": "New Delhi",
    "USA": "Washington DC",
    "UK": "London",
    "Canada": "Ottawa",
    "Australia": "Canberra"
}
for num, (country, city) in enumerate(country_dict.items()):
    print(num, country, city)

これってどういうことなのでしょうか? 以下のようなコードで考えるとよいかもしれません。

a, (b, c) = 0, ("USA", "Washington DC")

0はaに、そしてアンパックされた値がそれぞれ、(b, c)の中に代入されます。

enumlate関数と辞書、itemsを使った場合、アンパックする時にこの点に注意する必要があります。

eumlateの引数

それともう1点、このenumlate関数の引数についてお話いたします。

引数とは、関数に渡すデータのことでした。enumlate関数の引数にはstartという名前の引数があります。で、start=1として実行するとnumが0からではなく、1からはじまります。

for num, (country, city) in enumerate(country_dict.items(), start=1):
    print(num, country, city)

このstartを指定しない場合、0から始まりますが、指定した場合はその値から始まる、となります。

どういうときに使うのかというと、例えばユーザーの目に触れるところにこういう数字を同時に表示したいよというときに使います。

プログラミングになじみがないと、数字が0から始まるというのはちょっとなじみがないかと思います。

そういう0から始まるのになじみがない人に対して、0から始めないようにするということです。

enumlate関数の引数startも合わせて覚えておきましょう。

今回のまとめです。

enumlate関数が返すのは番号と値が入ったタプルです。

値リストであれば中身の1個ずつの要素ですし、辞書であればキーを返します。辞書の値を取得したい場合はvaluesメソッド、キーバーリューのペアを取得したい場合はitemsメソッドを使います。

それぞれ受け取り方がありますので、適切にコードを記述して任意の値を扱えるように練習しましょう。