Pythonで条件に一致するlist内の要素のインデックスを取得する

条件に一致するlist内の要素を検索して、見つかった要素のインデックスのリストを返すコードです。

def func1(lst, value):
    return [i for i, x in enumerate(lst) if x == value]

リストlstの値の中から変数valueに一致する値を検索して、そのインデックスのリストを返しています。

使用例

lst = [2, 1, 3, 1, 2]
idx = func1(lst, 1)
print(idx) #=> [1, 3]

リストlstの中から、値が1のものを検索して、そのインデックスを変数idxに代入しています。

list.index(x[, start[, end]])

リストのindex()メソッドを使った方法もあります。

listには、インデックスを返すメソッドindex()があります。

list.index(x[, start[, end]])

index()メソッドを使うと次のようなコードになります。

def func2(l, value):
    i = -1
    c = len(l)
    result = []
    while i < c:
        try:
            i = l.index(value, i + 1)
            result.append(i)
        except:
            return result
    return result

速度を比較してみる

最初のenumerateを使ったコードとlist.index()を使ったコードはどちらが早いでしょうか。

試してみました。
ソースコードは最後にあります。

>python test.py 5
func1は6.757836103439331秒かかりました
func2は8.353251934051514秒かかりました
「19994138」件見つかりました。

>python test.py 50
func1は5.679813385009766秒かかりました
func2は2.1373281478881836秒かかりました
「1997806」件見つかりました。

>python test.py 500
func1は6.612039089202881秒かかりました
func2は1.5565226078033447秒かかりました
「199632」件見つかりました。

list内に検索した要素が多いときはlist.index()が遅くなりました。
逆に、少ないときはlist.index()が早くなりました。

enumerateを使ったコードはlistの内容にかかわらず、速度は安定していました。

ソースコード

計測に使用したコードです。

from functools import wraps
import random
import sys
import time

def stop_watch(func):
    '''
    https://qiita.com/hisatoshi/items/7354c76a4412dffc4fd7
    を参考にしました
    '''
    @wraps(func)
    def wrapper(*args, **kargs) :
        start = time.time()
        result = func(*args,**kargs)
        elapsed_time =  time.time() - start
        print(f"{func.__name__}は{elapsed_time}秒かかりました")
        return result
    return wrapper

@stop_watch
def func1(l, value):
    return [i for i, x in enumerate(l) if x == value]

@stop_watch
def func2(l, value):
    i = -1
    c = len(l)
    result = []
    while i < c:
        try:
            i = l.index(value, i + 1)
            result.append(i)
        except:
            return result
    return result

def start(c):
    VALUE = 0
    L = [random.randrange(c) for i in range(100000000)]

    v1 = func1(L, VALUE)
    v2 = func2(L, VALUE)
    assert(v1 == v2)
    print(f'「{len(v1)}」件見つかりました。')

c = int(sys.argv[1])
start(c)

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください