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
Por simplicidad: newList = list(set(oldList))
Pero existen mejores opciones si desea obtener velocidad / ordenamiento / optimización en su lugar: http://www.peterbe.com/plog/uniqifiers-benchmark
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