条件に一致する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)