例えばテキストデータを舐めて単語の種類数を求めたいときとか、重複の無いリストが必要になる。
今まで、何も考えずに以下のように書いてた。
良くない例
>>> a = [1,2,2,1,3,4,1,2,3] >>> b = [] >>> for c in a: # aの中身をcで回す ... if c not in b: # cがbに入ってなければ追加 ... b.append(c) ... >>> b # 重複の無いリスト [1, 2, 3, 4]
setを使う
ぶっちゃけsetを使った方がコードが短かくて済む。そして速い。
ただし、リストと違って順序は保存されないので注意。
>>> a # aの中身を確認 [1, 2, 2, 1, 3, 4, 1, 2, 3] >>> b = set(a) >>> b # 上と同じ {1, 2, 3, 4}
しかし、この書き方をするなら一度aにすべての要素を突っ込まないと行けない。
最初にあげた単語を舐める例だと、テキストデータに出現しうるすべての単語を、一度aに突っ込まないといけない。
メモリ的にしんどい時は以下のように書くのが良い。
遅くなるけどリストに比べたらまだ速い。
>>> a [1, 2, 2, 1, 3, 4, 1, 2, 3] >>> b = set() # 空のsetを用意 >>> for c in a: ... b.add(c) # 重複しないように追加してくれる ... >>> b {1, 2, 3, 4}
速度比較
比較用コード
>>> # listで回す >>> def testList(arr): ... st = time.time() ... neoarr = [] ... for a in arr: ... if a not in neoarr: ... neoarr.append(a) ... print(time.time()-st) ... return neoarr ... >>> # listのset >>> def testSet1(arr): ... st = time.time() ... neoarr = set(arr) ... print(time.time()-st) ... return neoarr ... >>> # listを回してsetにadd >>> def testSet2(arr): ... st = time.time() ... neoarr = set() ... for a in arr: ... neoarr.add(a) ... print(time.time()-st) ... return neoarr
0から9までの整数をランダムに100万生成して、重複の無いリストを求める。
# listで回す >>> testList([random.randint(0,9) for _ in range(1000000)]) 0.14845705032348633 [3, 5, 8, 1, 4, 6, 9, 7, 0, 2] >>> testList([random.randint(0,9) for _ in range(1000000)]) 0.13007402420043945 [8, 1, 3, 0, 4, 5, 9, 2, 6, 7] >>> testList([random.randint(0,9) for _ in range(1000000)]) 0.1324453353881836 [0, 4, 5, 9, 7, 3, 6, 2, 8, 1] # listのset >>> testSet1([random.randint(0,9) for _ in range(1000000)]) 0.015883684158325195 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9} >>> testSet1([random.randint(0,9) for _ in range(1000000)]) 0.015897035598754883 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9} >>> testSet1([random.randint(0,9) for _ in range(1000000)]) 0.015883684158325195 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9} # listを回してsetにadd >>> testSet2([random.randint(0,9) for _ in range(1000000)]) 0.09662246704101562 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9} >>> testSet2([random.randint(0,9) for _ in range(1000000)]) 0.09584259986877441 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9} >>> testSet2([random.randint(0,9) for _ in range(1000000)]) 0.09663128852844238 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
ただ要素の種類を取り出したいだけならset使おう。