schedule2019-07-09

【Python】インデックスが多重配列の範囲外か判定する

インデックスが配列の範囲外かどうか確認するのが少し面倒な時がある。 1次元配列であればif 0 <= x and x < len(arr)で判定できるが、多重配列だと少々面倒くさい。

そこで、指定したインデックスが範囲外かどうか判定する関数を作成してみた。

  • 動作確認: Python 3.7

範囲外かどうか判定する関数

配列の次元が決まっている場合

原理はIndexErrorをtry文でキャッチするだけ。

import numpy as np # print用


def is_out_of_range(arr, x, y):
    try:
        arr[x][y]
    except IndexError:
        return True
    else:
        return False


if __name__ == "__main__":
    array = [[i for i in range(10)] for j in range(10)]
    print(np.array(array).shape) # (10, 10)

    print(is_out_of_range(array, 0, 0))   # False
    print(is_out_of_range(array, 1, 10))  # True
    print(is_out_of_range(array, 50, 0))  # True

    # 負の値だとFalse
    print(is_out_of_range(array, -1, 0))  # False

インデックスよりも大きいときTrueになっていることが分かる。 ただ、arr[-1]で末尾の要素が取れるように負の値はFalseになる。 これはどうしたもんか。

配列の次元数に対応させる

これが本命(?)。

配列の次元と同じ数だけインデックスを渡せば範囲外か検知できる。 可変長引数を使ってみた。

import numpy as np


def recall(arr, index):
    if len(index) == 0:
        return False
    else:
        # if index[0] < 0:
        #     raise IndexError("error!")
        recall(arr[index[0]], index[1:])


def is_out_of_range(arr, *index):
    try:
        return recall(arr, index)
    except IndexError:
        return True
    else:
        return False


if __name__ == "__main__":
    array = [[i for i in range(10)] for j in range(10)]
    print(np.array(array).shape)

    print(is_out_of_range(array, 0, 0))   # False
    print(is_out_of_range(array, 1, 10))  # True
    print(is_out_of_range(array, 50, 0))  # True

    array = [[[i for i in range(10)] for j in range(10)] for k in range(10)]
    print(np.array(array).shape)

    print(is_out_of_range(array, 0, 0, 0))  # False
    print(is_out_of_range(array, 1, 10, 1))  # True
    print(is_out_of_range(array, -1, 2, 0))  # False

おわりに

作ってはみたが自分で活用する機会はない。。。