python list loops set

graph python



Mejor/Más rápido para enlazar a través de un conjunto o lista? (5)

Si tengo una lista de Python que tiene muchos duplicados, y quiero iterar a través de cada elemento, pero no a través de los duplicados, ¿es mejor usar un conjunto (como en set(mylist) , o encontrar otra forma de crear una lista? sin duplicados? Estaba pensando solo en recorrer la lista y buscar duplicados, pero pensé que eso es lo que set() cuando se inicializa.

Así que si mylist = [3,1,5,2,4,4,1,4,2,5,1,3] y realmente solo quiero pasar por [1,2,3,4,5] (orden no importa), ¿debería usar set(mylist) u otra cosa?

Una alternativa es posible en el último ejemplo, ya que la lista contiene todos los enteros entre su valor mínimo y máximo, podría recorrer el range(min(mylist),max(mylist)) o a través de set(mylist) . ¿Debería generalmente evitar el uso de set en este caso? Además, ¿sería más lento encontrar el min y el max que simplemente crear el set ?

En el caso del último ejemplo, el set es más rápido:

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



Si bien un set puede ser lo que quiere estructurar, la pregunta es qué es más rápido. Una lista es más rápida. Su código de ejemplo no compara con precisión el set contra la list porque está convirtiendo de una lista a un conjunto en set_loop , y luego está creando la list que va a recorrer en list_loop . El conjunto y la lista a través de los cuales se itera deberían construirse y almacenarse previamente en la memoria, y simplemente pasar por el bucle para ver qué estructura de datos es más rápida en la iteración:

ids_list = range(1000000) sids_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


Si la lista varía en bucle grande dos veces, tomará mucho tiempo y más en la segunda vez que está bucleando un conjunto, no una lista, y como sabemos que iterar sobre un conjunto es más lento que la lista.

Creo que necesitas el poder del generator y el set .

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))

fuera puesto:

0.024003583388435043 0.010424674188938422

Nota: esta orden técnica está garantizada


Solo usa un set . Su semántica es exactamente lo que quieres: una colección de artículos únicos.

Técnicamente, estará iterando por la lista dos veces: una para crear el conjunto, una para su ciclo real. Pero estarías haciendo tanto trabajo o más con cualquier otro enfoque.


set es lo que quieres, por lo que deberías usar set . ¡Intentar ser inteligente introduce errores sutiles como olvidar agregar uno al max(mylist) ! Codifica a la defensiva. Preocúpese por lo que es más rápido cuando determine que es demasiado lento.

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