¿Hay una manera pitónica de verificar si una lista ya está ordenada ASC
oDESC
listtimestamps = [1, 2, 3, 5, 6, 7]
algo así isttimestamps.isSorted()
regresa True
o False
.
Quiero ingresar una lista de marcas de tiempo para algunos mensajes y verificar si las transacciones aparecieron en el orden correcto.
key
función para usar.key=lambda x, y: x < y
hace un buen incumplimiento.def isSorted(x, key = lambda x: x): return all([key(x[i]) <= key(x[i + 1]) for i in xrange(len(x) - 1)])
operator.le
debería ser más rápido que el lambdal = [1, 2, 3, 4, 1, 6, 7, 8, 7] all(l[i] <= l[i+1] for i in xrange(len(l)-1))
imprimir como resultado:True
xrange
, solo userange
. Me saleNameError: name 'xrange' is not defined
cuando ejecuto ese código. Lo cambié a solo usar enrange
lugar dexrange
y eso funciona bien. Ver: stackoverflow.com/questions/15014310/…Yo solo usaría
a menos que sea una lista muy grande, en cuyo caso es posible que desee crear una función personalizada.
si solo va a ordenarlo si no está ordenado, entonces olvide el cheque y ordénelo.
y no lo pienses demasiado.
si quieres una función personalizada, puedes hacer algo como
Esto será O (n) si la lista ya está ordenada (¡y O (n) en un
for
ciclo!) Así que, a menos que espere que no esté ordenada (y sea bastante aleatoria) la mayor parte del tiempo, lo haría, de nuevo, solo ordena la lista.fuente
Este formulario iterador es 10-15% más rápido que usar la indexación de enteros:
fuente
izip
yislice
desde itertools para hacerlo más rápido.Una hermosa manera de implementar esto es usar la
imap
función desdeitertools
:Esta implementación es rápida y funciona en cualquier iterable.
fuente
is_sorted(iter([1,2,3,2,5,8]))
o un generador equivalente. Necesita usar un iterador independiente paratail
, intenteitertools.tee
.iter(x) is x
para los iteradoresitertools.imap
ha cambiado el nombre a[__builtins__.]map
.Ejecuté un punto de referencia
y. Estos puntos de referencia se ejecutaron en un MacBook Pro 2010 13 "(Core2 Duo 2.66GHz, 4GB 1067MHz DDR3 RAM, Mac OS X 10.6.5).sorted(lst, reverse=True) == lst
fui el más rápido para listas largas yall(l[i] >= l[i+1] for i in xrange(len(l)-1))
el más rápido para listas cortasACTUALIZACIÓN: Revisé el script para que pueda ejecutarlo directamente en su propio sistema. La versión anterior tenía errores. Además, he agregado entradas clasificadas y no clasificadas.all(l[i] >= l[i+1] for i in xrange(len(l)-1))
sorted(l, reverse=True) == l
all(l[i] >= l[i+1] for i in xrange(len(l)-1))
all(l[i] >= l[i+1] for i in xrange(len(l)-1))
Entonces, en la mayoría de los casos hay un claro ganador.ACTUALIZACIÓN: las respuestas de aaronsterling (# 6 y # 7) son en realidad las más rápidas en todos los casos. # 7 es el más rápido porque no tiene una capa de indirección para buscar la clave.
fuente
enumerate
son incorrectas.enumerate(l[1:])
debería ser reemplazado porenumerate(l[1:], 1)
enumerate(l[1:])
porenumerate(l[1:], 1)
podría reemplazarl[i-1]
porl[i]
.L5=range(100); random.shuffle(L5)
entonces # 5 es relativamente lento. En este caso, el # 7 modificado es más rápido en general codepad.org/xmWPxHQYHaría esto (robando muchas respuestas aquí [Aaron Sterling, Wai Yip Tung, más o menos de Paul McGuire] y principalmente Armin Ronacher ):
Una cosa buena: no tiene que darse cuenta del segundo iterable para la serie (a diferencia de un segmento de lista).
fuente
key
.key
debe usarse para convertir elementos en valores comparables.Yo uso este one-liner basado en numpy.diff ():
Realmente no lo he cronometrado con ningún otro método, pero supongo que es más rápido que cualquier método Python puro, especialmente para n grande, ya que el bucle en numpy.diff (probablemente) se ejecuta directamente en C (n-1 sustracciones seguidas de n -1 comparaciones).
Sin embargo, debe tener cuidado si x es un int sin signo, lo que podría causar un flujo de entero entero silencioso en numpy.diff (), lo que da como resultado un falso positivo. Aquí hay una versión modificada:
fuente
Esto es similar a la respuesta principal, pero me gusta más porque evita la indexación explícita. Suponiendo que su lista tenga el nombre
lst
, puede generar(item, next_item)
tuplas a partir de su lista conzip
:En Python 3,
zip
ya devuelve un generador, en Python 2 puede usaritertools.izip
para una mejor eficiencia de memoria.Pequeña demostración:
El último falla cuando
(3, 2)
se evalúa la tupla .Bonificación: comprobación de generadores finitos (!) Que no pueden indexarse:
Asegúrate de usar
itertools.izip
aquí si estás usando Python 2, de lo contrario anularías el propósito de no tener que crear listas a partir de los generadores.fuente
islice
para optimizar para cortar. También en el módulo itertools.all(x <= y for x, y in izip(lst, islice(lst, 1)))
.SapphireSun tiene toda la razón. Solo puedes usar
lst.sort()
. La implementación de clasificación de Python (TimSort) verifica si la lista ya está ordenada. Si es así, sort () se completará en tiempo lineal. Suena como una forma pitónica para asegurar que una lista esté ordenada;)fuente
Aunque no creo que haya una garantía de que la función
sorted
incorporada llame a su función cmpi+1, i
, parece que lo hace para CPython.Entonces podrías hacer algo como:
O de esta manera (sin declaraciones if -> EAFP salió mal? ;-)):
fuente
No es muy pitónico, pero necesitamos al menos una
reduce()
respuesta, ¿verdad?La variable del acumulador simplemente almacena el último valor verificado, y si algún valor es menor que el valor anterior, el acumulador se establece en infinito (y, por lo tanto, seguirá siendo infinito al final, ya que el 'valor anterior' siempre será mayor que el actual).
fuente
Como señaló @aaronsterling, la siguiente solución es la más corta y parece más rápida cuando la matriz está ordenada y no es demasiado pequeña: def is_sorted (lst): return (sorted (lst) == lst)
Si la mayoría de las veces la matriz no está ordenada, sería deseable usar una solución que no escanee la matriz completa y devuelva False tan pronto como se descubra un prefijo no ordenado. La siguiente es la solución más rápida que pude encontrar, no es particularmente elegante:
Usando el punto de referencia de Nathan Farrington, esto logra un mejor tiempo de ejecución que usar sorted (lst) en todos los casos, excepto cuando se ejecuta en la lista ordenada grande.
Aquí están los resultados de referencia en mi computadora.
sorted (lst) == lst solution
Segunda solución:
fuente
Si desea la forma más rápida para matrices numpy, use numba , que si usa conda ya debería estar instalado
El código será rápido porque será compilado por numba
y entonces:
fuente
Solo para agregar otra forma (incluso si requiere un módulo adicional)
iteration_utilities.all_monotone
::Para verificar el pedido DESC:
También hay un
strict
parámetro si necesita verificar estrictamente (si los elementos sucesivos no deben ser iguales) secuencias monotónicas.No es un problema en su caso, pero si sus secuencias contienen
nan
valores, algunos métodos fallarán, por ejemplo con sorted:Tenga en cuenta que
iteration_utilities.all_monotone
funciona más rápido en comparación con las otras soluciones mencionadas aquí, especialmente para las entradas no ordenadas (ver punto de referencia ).fuente
Perezoso
fuente
all(a <= b for a, b in zip(l, l[1:]))
l
es un generador y no admite el corte.Python 3.6.8
fuente
La forma más simple:
fuente
El valor de reducción derivado es una tupla de 3 partes de ( sortedSoFarFlag , firstTimeFlag , lastElementValue ). En un primer momento se inicia con (
True
,True
,None
), que también se utiliza como el resultado de una lista vacía (considerado como ordenados, porque no hay elementos fuera de la orden). A medida que procesa cada elemento, calcula nuevos valores para la tupla (utilizando valores de tupla anteriores con el siguiente elementValue):El resultado final de la reducción es una tupla de:
El primer valor es el que nos interesa, por lo que usamos
[0]
para obtenerlo del resultado de reducción.fuente
Como no veo esta opción arriba, la agregaré a todas las respuestas. Deje denotar la lista por
l
, entonces:fuente
Una solución que usa expresiones de asignación (agregadas en Python 3.8):
Da:
fuente
De hecho, esta es la forma más corta de hacerlo utilizando la recursividad:
si está ordenado se imprimirá Verdadero, de lo contrario se imprimirá Falso
fuente
RuntimeError: maximum recursion depth exceeded
para largas listas. Tratarany_list = range(1000)
.Que tal este ? Simple y directo.
fuente
Definitivamente funciona en Python 3 y superior para enteros o cadenas:
================================================== ===================
Otra forma de encontrar si la lista dada está ordenada o no
fuente