web-dev-qa-db-ja.com

セットまたはリストをループするより良い/速い?

pythonリストに多くの重複がある場合、重複を介さずに各項目を反復処理したい場合は、set(mylist)、または重複のないリストを作成する別の方法を見つけますか?リストをループして重複をチェックすることを考えていましたが、それがset()が初期化されたときに行うことを考えました。

_mylist = [3,1,5,2,4,4,1,4,2,5,1,3]_で、本当に_[1,2,3,4,5]_をループしたい場合(順序は関係ありません)、set(mylist)または他の何かを使用する必要がありますか?

最後の例では、リストがその最小値と最大値の間のすべての整数を含むため、別の方法が可能です。range(min(mylist),max(mylist))またはset(mylist)をループできます。この場合、一般にsetを使用しないようにする必要がありますか?また、minmaxを見つけることは、単にsetを作成するよりも遅いでしょうか?


最後の例の場合、setの方が高速です。

_from numpy.random import random_integers
ids = random_integers(1e3,size=1e6)

def set_loop(mylist):
    idlist = []
    for id in set(mylist):
        idlist.append(id)
    return idlist

def list_loop(mylist):
    idlist = []
    for id in range(min(mylist),max(mylist)):
        idlist.append(id)
    return idlist

%timeit set_loop(ids)
#1 loops, best of 3: 232 ms per loop

%timeit list_loop(ids)
#1 loops, best of 3: 408 ms per loop
_
35
askewchan

setを使用してください。そのセマンティクスはまさにあなたが望むものです:ユニークなアイテムのコレクション。

技術的には、リストを2回繰り返します。1回はセットを作成し、もう1回は実際のループに使用します。しかし、他のアプローチでも同じくらいの作業を行うことになります。

37
Eevee

setは必要なものなので、setを使用する必要があります。賢くしようとすると、tomax(mylist)を1つ追加するのを忘れるなどの微妙なバグが発生します。防御的にコーディングします。遅すぎると判断した場合の高速化について心配します。

range(min(mylist), max(mylist) + 1)  # <-- don't forget to add 1
10
John La Rooy

簡単にするために:newList = list(set(oldList))

ただし、代わりにspeed/ordering/optimizationを取得する場合は、より優れたオプションがあります。 http://www.peterbe.com/plog/uniqifiers-benchmark

5
GordonsBeard

setが構造的に必要な場合もありますが、問題はより高速なものです。リストは高速です。リストからセットに変換するため、サンプルコードはsetlistを正確に比較しませんinset_loopを作成し、listを作成します-inlist_loop。繰り返し処理するセットとリストは、事前に構築し、メモリ内に作成し、単純にループ処理して、繰り返し処理でどのデータ構造が高速かを確認する必要があります。

ids_list = range(1000000)
ids_set = set(ids)
def f(x):
    for i in x:
         pass

%timeit f(ids_set)
#1 loops, best of 3: 214 ms per loop
%timeit f(ids_list)
#1 loops, best of 3: 176 ms per loop
5
hamx0r

私はリストが2回ループすると大きく変化し、リストではなくセットをループしているときに2回目に多くの時間がかかります。

generatorsetのパワーが必要だと思います。

def first_test():

    def loop_one_time(my_list):
        # create a set to keep the items.
        iterated_items = set()
        # as we know iterating over list is faster then list.
        for value in my_list: 
            # as we know checking if element exist in set is very fast not
            # metter the size of the set.
            if value not in iterated_items:  
                iterated_items.add(value) # add this item to list
                yield value


    mylist = [3,1,5,2,4,4,1,4,2,5,1,3]

    for v in loop_one_time(mylist):pass



def second_test():
    mylist = [3,1,5,2,4,4,1,4,2,5,1,3]
    s = set(mylist)
    for v in s:pass


import timeit

print(timeit.timeit('first_test()', setup='from __main__ import first_test', number=10000))
print(timeit.timeit('second_test()', setup='from __main__ import second_test', number=10000))

出力:

   0.024003583388435043
   0.010424674188938422

注:この手法の順序は保証されています

1
Elegant Odoo