trsing’s diary

勉強、読んだ本、仕事で調べたこととかのメモ。

pythonで二つのリストの比較

二つのリスト(A,B)を比較してAの各要素がBにあるかないか表示できたら便利ということがあったのでpythonで書いてみた。

listA=['a','b','c','d','e','f']
listB=['b','d','e','g','h']

#listAの各要素をkey、keyがlistBに含まれれば'あり'、含まれなければ'なし'をvalueにして辞書型作成
dct={a:'あり' if a in listB else 'なし' for a in listA}
for ky in dct:
    print(ky+":"+dct[ky])

結果:
a:なし
b:あり
c:なし
d:あり
e:あり
f:なし

二つのリストの和集合に対して積集合をあり、差集合をなしにする場合

dct2={a:'あり' if a in set(listA) & set(listB) else 'なし' for a in set(listA) | set(listB)}
for k,v in sorted(dct2.items()):
    print(k+":"+v)

結果:
a:なし
b:あり
c:なし
d:あり
e:あり
f:なし
g:なし
h:なし

便利だ・・・

効率

効率(forの式毎度評価されてない?)が気になったのでリファレンスを見てみるとforの「式リストは一度だけ評価」。 ifのとこは毎回実行されるよなあということでちょっと確認。

import numpy as np
listA=np.random.randint(1,10000,size=5000)
listB=np.random.randint(1,10000,size=5000)

start=time.time()
dct={a:'あり' if a in set(listA) & set(listB) else 'なし' for a in set(listA) | set(listB)}
elapsed_time=time.time()-start
print('elapsed:{0}'.format(elapsed_time))

#forの式(set(listA) | set(listB))を先に評価しておく
start2=time.time()
orab=set(listA) | set(listB)
dct2={a:'あり' if a in set(listA) & set(listB) else 'なし' for a in orab}
elapsed_time2=time.time()-start2
print('elapsed2:{0}'.format(elapsed_time2))

#ifの式(set(listA)&set(listB))を先に評価しておく
start3=time.time()
uni=set(listA)&set(listB)
dct3={a:'あり' if a in uni else 'なし' for a in set(listA) | set(listB)}
elapsed_time3=time.time()-start3
print('elapsed3:{0}'.format(elapsed_time3))

#forの式(set(listA) | set(listB))、ifの式(set(listA)&set(listB))を先に評価しておく
start4=time.time()
uni2=set(listA)&set(listB)
orab2=set(listA)| set(listB)
dct4={a:'あり' if a in uni2 else 'なし' for a in orab2}
elapsed_time4=time.time()-start4
print('elapsed4:{0}'.format(elapsed_time4))

結果:
elapsed:12.282702445983887
elapsed2:12.242701768875122
elapsed3:0.005000114440917969
elapsed4:0.006000995635986328

forの式は一回、ifの式は毎度評価されてるということでよさそう。
ifの式は先に評価したものを使おう。