2010-05-14 20 views
120

En Python, ¿qué estructura de datos es más eficiente/rápida? Suponiendo que el orden no es importante para mí y estaría buscando duplicados de todos modos, ¿Python es más lento que una lista de Python?Python Conjuntos vs Listas

Respuesta

143

Depende de lo que piense hacer con él.

Los conjuntos son significativamente más rápido cuando se trata de determinar si un objeto está presente en el conjunto (como en x in s), pero son más lentas que las listas cuando se trata de iterar sobre su contenido.

Puede usar el timeit module para ver cuál es más rápido para su situación.

+1

Para su punto: "Los conjuntos son significativamente más rápidos", ¿cuál es la implementación subyacente que lo hace más rápido? – overexchange

+7

@overexchange tablas hash http://stackoverflow.com/a/3949350/125507 – endolith

+1

https://en.wikipedia.org/wiki/Hash_table –

102

Cuando desee almacenar algunos valores sobre los cuales realizará iteraciones, las construcciones de listas de Python son ligeramente más rápidas. Sin embargo, si va a almacenar valores (únicos) para verificar su existencia, los conjuntos son significativamente más rápidos.

Resulta que las tuplas funcionan casi de la misma manera que las listas, pero usan menos memoria al eliminar la capacidad de modificarlas después de la creación (inmutables).

iteración

>>> def iter_test(iterable): 
...  for i in iterable: 
...   pass 
... 
>>> from timeit import timeit 
>>> timeit(
...  "iter_test(iterable)", 
...  setup="from __main__ import iter_test; iterable = set(range(10000))", 
...  number=100000) 
12.666952133178711 
>>> timeit(
...  "iter_test(iterable)", 
...  setup="from __main__ import iter_test; iterable = list(range(10000))", 
...  number=100000) 
9.917098999023438 
>>> timeit(
...  "iter_test(iterable)", 
...  setup="from __main__ import iter_test; iterable = tuple(range(10000))", 
...  number=100000) 
9.865639209747314 

determinar si un objeto está presente

>>> def in_test(iterable): 
...  for i in range(1000): 
...   if i in iterable: 
...    pass 
... 
>>> from timeit import timeit 
>>> timeit(
...  "in_test(iterable)", 
...  setup="from __main__ import in_test; iterable = set(range(1000))", 
...  number=10000) 
0.5591847896575928 
>>> timeit(
...  "in_test(iterable)", 
...  setup="from __main__ import in_test; iterable = list(range(1000))", 
...  number=10000) 
50.18339991569519 
>>> timeit(
...  "in_test(iterable)", 
...  setup="from __main__ import in_test; iterable = tuple(range(1000))", 
...  number=10000) 
51.597304821014404 
+3

He encontrado eso (Initializing set -> 5.5300979614257812) (Lista de inicialización -> 1.8846848011016846) (Inicializando la tupla -> 1.8730108737945557) Elementos de tamaño 10,000 en mi núcleo intel i5 quad core con 12GB de RAM. Esto también debe tenerse en cuenta. – ThePracticalOne

+3

He actualizado el código para eliminar la creación del objeto ahora. La fase de configuración de los bucles de tiempo solo se llama una vez (https://docs.python.org/2/library/timeit.html#timeit.Timer.timeit). –

8

rendimiento de lista:

>>> import timeit 
>>> timeit.timeit(stmt='10**6 in a', setup='a = range(10**6)', number=100000) 
0.008128150348026608 

rendimiento Set:

>>> timeit.timeit(stmt='10**6 in a', setup='a = set(range(10**6))', number=100000) 
0.005674857488571661 

Es posible que desee considerar Tuplas ya que son similares a las listas, pero no pueden ser modificados. Toman un poco menos de memoria y son más rápidos de acceder. No son tan flexibles, pero son más eficientes que las listas. Su uso normal es servir como claves del diccionario.

Los conjuntos también son estructuras de secuencia pero con dos diferencias de listas y tuplas. Aunque los juegos sí tienen un orden, ese orden es arbitrario y no está bajo el control del programador. La segunda diferencia es que los elementos en un conjunto deben ser únicos.

set por definición. [python | wiki].

>>> x = set([1, 1, 2, 2, 3, 3]) 
>>> x 
{1, 2, 3} 
+4

En primer lugar, debe actualizar al enlace de tipo integrado 'set' (http://docs.python.org/2/library/stdtypes.html#set) no a la biblioteca obsoleta' sets'. En segundo lugar, "los conjuntos también son estructuras de secuencia", lea lo siguiente del enlace de tipo incorporado: "Al ser una colección desordenada, los conjuntos no registran la posición del elemento ni el orden de inserción. Por consiguiente, los conjuntos no admiten indexación, corte u otro comportamiento similar a una secuencia ". – Seaux

3

Set victorias debido a la casi instantánea 'contiene' cheques: https://en.wikipedia.org/wiki/Hash_table

Lista aplicación: por lo general una matriz, de bajo nivel cercano al metal, bueno para la iteración y de acceso aleatorio por el índice de elemento.

Conjunto aplicación: https://en.wikipedia.org/wiki/Hash_table, no iterar sobre una lista, pero se encuentra con el elemento calculando un hash de de la clave, por lo que depende de la naturaleza de los elementos clave y la función hash. Similar a lo que se usa para dict.Sospecho que list podría ser más rápido si tiene muy pocos elementos (< 5), cuanto mayor sea el elemento, mejor funcionará el set para un control de contenido. También es rápido para agregar y eliminar elementos.

NOTA: Si el list ya está ordenado, buscando los list podría ser bastante rápido, pero para los casos habituales de un set es más rápido y más sencillo para contiene comprobaciones.