IndexError: list index out of range

By | 2012/8/7 火曜日

リスト(配列)に対して存在しないインデックを指定した際に発生するのがこの例外。
“IndexError: list index out of range”
Pythonの話ですけど。

一般的には配列の長さをlenで取得してその範囲に収まるようにすれば問題無いのです。
でもそういうやつばかりじゃない時にちょっと書き方が煮詰まったのでとりあえずブログに書いてみる。

たとえばcsvのファイルがあってそれをリスト&辞書型に格納する。

test.txt(名前[必須]、血液型[任意]、年齢[任意])

hoge,B,33
fuga
piyo,AB

Python側はこんな感じ

result = []
with open('test.txt', 'r') as f:
    for line in f:
        tmp = line.rstrip().split(',')
        result.append({
            'name': tmp[0],
            'blood_type': tmp[1],
            'age': tmp[2]
        })

print result

これを実行してみると

Traceback (most recent call last):
  File "hoge.py", line 7, in 
    'blood_type': tmp[1],
IndexError: list index out of range

test.txtの2行目に名前しか入ってないのでIndexErrorが発生。
test.txt作る時にカンマの数合わせて入れろと思うことも無いんだけどそうじゃない時もあるってことで進める。

とりあえずIndexErrorが発生しない様に書き換えたのが以下のコード。
三項演算子使って配列の長さ判断した形。

result = []
with open('hoge.txt', 'r') as f:
    for line in f:
        tmp = line.rstrip().split(',')
        result.append({
            'name': tmp[0],
            'blood_type': tmp[1] if len(tmp) > 1 else '',
            'age': tmp[2] if len(tmp) > 2 else ''
        })

print result

結果は欲しい形でとれた。

[{'age': '33', 'name': 'hoge', 'blood_type': 'B'}, {'age': '', 'name': 'fuga', 'blood_type': ''}, {'age': '', 'name': 'piyo', 'blood_type': 'AB'}]

もう少し考えて下の形にしてみたもののあまり変わらない。
コードは小さくなったけどわかりやすくなったのかは疑問。

result = []
with open('hoge.txt', 'r') as f:
    for line in f:
        tmp = line.rstrip().split(',')
        result.append({
            'name': tmp[0],
            'blood_type': tmp[1] if tmp[1:] else '',
            'age': tmp[2] if tmp[2:] else ''
        })

print result

splitの後にtmpに[”, ”, ”]を追加してしまえば辞書型に変換するときに三項演算子使わなくてもよくなるのですがそれもいまいちかなと。

PHPだとissetがあるしrubyだとnilが返されるのでもうちょっと楽なんですけどね。
stackoverflow先生も漁って見たけどよい解決見当たらない。
他の人がこういった場合にどう書いているのか興味あるところです。ぜひコメントで教えて下さい。

3 thoughts on “IndexError: list index out of range

  1. shirebito

    zipを利用するのはどうでしょうか?

    fields = [‘name’, ‘blood_type’, ‘age’]
    result = []

    with open(‘hoge.txt’, ‘r’) as f:
    for line in f:
    tmp = line.rstrip().split(‘,’)
    result.append({name:value for name, value in zip(fields, tmp)})

    print result

  2. t Post author

    すばらしい!
    zip関数知りませんでした。
    これですっきり書けます。

    shirebitoさんコメントありがとうございました。

コメントを残す

メールアドレスが公開されることはありません。