Pregunta ¿La mejor manera de crear una lista "invertida" en Python?


En Python, ¿cuál es la mejor manera de crear una nueva lista cuyos elementos son los mismos que los de cualquier otra lista, pero en orden inverso? (No quiero modificar la lista existente en su lugar).

Aquí hay una solución que se me ha ocurrido:

new_list = list(reversed(old_list))

También es posible duplicar old_list luego invierta el duplicado en su lugar:

new_list = list(old_list) # or `new_list = old_list[:]`
new_list.reverse()

¿Hay alguna mejor opción que he pasado por alto? Si no, ¿hay alguna razón de peso (como la eficiencia) para usar uno de los enfoques anteriores sobre el otro?


73
2017-09-14 02:06


origen


Respuestas:


newlist = oldlist[::-1]

los [::-1] slicing (que a mi esposa Anna le gusta llamar "el smiley marciano" ;-) significa: cortar toda la secuencia, con un paso de -1, es decir, al revés. Funciona para todas las secuencias.

Tenga en cuenta que esto (y las alternativas que mencionas) es equivalente a una "copia superficial", es decir: si los elementos son mutables y llamas mutadores sobre ellos, las mutaciones en los elementos contenidos en la lista original también están en los artículos en la lista invertida, y viceversa versa. Si necesita evitar eso, un copy.deepcopy (aunque siempre es una operación potencialmente costosa), seguido en este caso por un .reverse, es la única buena opción.


177
2017-09-14 02:07



Ahora vamos a timeit. Insinuación: Alex [::-1] es más rápido :)

$ p -m timeit "ol = [1, 2, 3]; nl = list(reversed(ol))"
100000 loops, best of 3: 2.34 usec per loop

$ p -m timeit "ol = [1, 2, 3]; nl = list(ol); nl.reverse();"
1000000 loops, best of 3: 0.686 usec per loop

$ p -m timeit "ol = [1, 2, 3]; nl = ol[::-1];"
1000000 loops, best of 3: 0.569 usec per loop

$ p -m timeit "ol = [1, 2, 3]; nl = [i for i in reversed(ol)];"
1000000 loops, best of 3: 1.48 usec per loop


$ p -m timeit "ol = [1, 2, 3]*1000; nl = list(reversed(ol))"
10000 loops, best of 3: 44.7 usec per loop

$ p -m timeit "ol = [1, 2, 3]*1000; nl = list(ol); nl.reverse();"
10000 loops, best of 3: 27.2 usec per loop

$ p -m timeit "ol = [1, 2, 3]*1000; nl = ol[::-1];"
10000 loops, best of 3: 24.3 usec per loop

$ p -m timeit "ol = [1, 2, 3]*1000; nl = [i for i in reversed(ol)];"
10000 loops, best of 3: 155 usec per loop

Actualizar: Método de compilación de lista agregado sugerido por inspectorG4dget. Dejaré que los resultados hablen por sí mismos.


46
2017-09-14 02:18



Ajustes

Merece la pena proporcionar un punto de referencia / ajuste de referencia para los cálculos de tiempo por sdolan que muestran el rendimiento de 'invertido' sin la frecuencia que a menudo es innecesaria. list() conversión. Esta list() la operación agrega 26 usos adicionales al tiempo de ejecución y solo es necesaria en caso de que un iterador sea inaceptable.

Resultados:

reversed(lst) -- 11.2 usecs

list(reversed(lst)) -- 37.1 usecs

lst[::-1] -- 23.6 usecs

Cálculos:

# I ran this set of 100000 and came up with 11.2, twice:
python -m timeit "ol = [1, 2, 3]*1000; nl = reversed(ol)"
100000 loops, best of 3: 11.2 usec per loop

# This shows the overhead of list()
python -m timeit "ol = [1, 2, 3]*1000; nl = list(reversed(ol))"
10000 loops, best of 3: 37.1 usec per loop

# This is the result for reverse via -1 step slices
python -m timeit "ol = [1, 2, 3]*1000;nl = ol[::-1]"
10000 loops, best of 3: 23.6 usec per loop

Conclusiones

La conclusión de estas pruebas es reversed() es más rápido que la porción [::-1] por 12.4 usos


6
2018-05-13 03:23