Existe-t-il un moyen pythonique de vérifier si une liste est déjà triée ASC
ouDESC
listtimestamps = [1, 2, 3, 5, 6, 7]
quelque chose comme isttimestamps.isSorted()
ça revient True
ou False
.
Je souhaite saisir une liste d'horodatages pour certains messages et vérifier si les transactions sont apparues dans le bon ordre.
key
fonction à utiliser.key=lambda x, y: x < y
fait un bon défaut.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
devrait être plus rapide que le lambdal = [1, 2, 3, 4, 1, 6, 7, 8, 7] all(l[i] <= l[i+1] for i in xrange(len(l)-1))
imprimer comme résultat:True
xrange
plus, il suffit d'utiliserrange
. Je reçoisNameError: name 'xrange' is not defined
quand j'exécute ce code. Je l'ai changé pour simplement utiliserrange
au lieu dexrange
et cela fonctionne très bien. Voir: stackoverflow.com/questions/15014310/…Je voudrais juste utiliser
sauf s'il s'agit d'une très grande liste, auquel cas vous souhaiterez peut-être créer une fonction personnalisée.
si vous voulez simplement le trier s'il n'est pas trié, oubliez le chèque et triez-le.
et n'y pensez pas trop.
si vous voulez une fonction personnalisée, vous pouvez faire quelque chose comme
Ce sera O (n) si la liste est déjà triée (et O (n) dans une
for
boucle!) Donc, à moins que vous ne vous attendiez à ce qu'elle ne soit pas triée (et assez aléatoire) la plupart du temps, je le ferais, encore une fois, triez simplement la liste.la source
Cette forme d'itérateur est 10 à 15% plus rapide que l'utilisation de l'indexation d'entiers:
la source
izip
et àislice
partir d'itertools pour la rendre plus rapide.Une belle façon d'implémenter cela est d'utiliser la
imap
fonction deitertools
:Cette implémentation est rapide et fonctionne sur tous les itérables.
la source
is_sorted(iter([1,2,3,2,5,8]))
ou un générateur équivalent. Vous devez utiliser un itérateur indépendant pourtail
, essayezitertools.tee
.iter(x) is x
pour les itérateursitertools.imap
a été renommé en[__builtins__.]map
.J'ai dirigé un benchmark
etj'aisorted(lst, reverse=True) == lst
all(l[i] >= l[i+1] for i in xrange(len(l)-1))
été le plus rapide pour les longues listes etle plus rapide pour les listes courtes. Ces tests ont été exécutés sur un MacBook Pro 2010 13 "(Core2 Duo 2,66 GHz, 4 Go de RAM DDR3 à 1067 MHz, Mac OS X 10.6.5).METTRE À JOUR: J'ai révisé le script afin que vous puissiez l'exécuter directement sur votre propre système. La version précédente avait des bugs. En outre, j'ai ajouté des entrées triées et non triées.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))
Donc, dans la plupart des cas, il y a un gagnant clair.MISE À JOUR: les réponses d'aaronsterling (# 6 et # 7) sont en fait les plus rapides dans tous les cas. Le n ° 7 est le plus rapide car il n'a pas de couche d'indirection pour rechercher la clé.
la source
enumerate
sont incorrectes.enumerate(l[1:])
devrait être remplacé parenumerate(l[1:], 1)
enumerate(l[1:])
par,enumerate(l[1:], 1)
vous pouvez remplacerl[i-1]
parl[i]
.L5=range(100); random.shuffle(L5)
alors # 5 est relativement lent. Dans ce cas, le # 7 modifié est globalement plus rapide codepad.org/xmWPxHQYJe ferais ceci (voler de nombreuses réponses ici [Aaron Sterling, Wai Yip Tung, en quelque sorte de Paul McGuire] et surtout Armin Ronacher ):
Une bonne chose: vous n'avez pas à réaliser le deuxième itérable pour la série (contrairement à une tranche de liste).
la source
key
.key
doit être utilisé pour transformer des éléments en valeurs comparables.J'utilise ce one-liner basé sur numpy.diff ():
Je ne l'ai pas vraiment chronométré par rapport à une autre méthode, mais je suppose que c'est plus rapide que n'importe quelle méthode Python pure, en particulier pour les grands n, car la boucle dans numpy.diff (probablement) s'exécute directement en C (n-1 soustractions suivies de n -1 comparaisons).
Cependant, vous devez faire attention si x est un entier non signé, ce qui peut entraîner un dépassement d'entier silencieux dans numpy.diff (), entraînant un faux positif. Voici une version modifiée:
la source
Ceci est similaire à la réponse du haut, mais je l'aime mieux car cela évite l'indexation explicite. En supposant que votre liste porte le nom
lst
, vous pouvez générer des(item, next_item)
tuples à partir de votre liste aveczip
:En Python 3,
zip
renvoie déjà un générateur, en Python 2 vous pouvez utiliseritertools.izip
pour une meilleure efficacité de la mémoire.Petite démo:
Le dernier échoue lorsque le tuple
(3, 2)
est évalué.Bonus: vérification des générateurs finis (!) Non indexables:
Assurez-vous de l'utiliser
itertools.izip
ici si vous utilisez Python 2, sinon vous iriez à l'encontre de l'objectif de ne pas avoir à créer de listes à partir des générateurs.la source
islice
pour optimiser le tranchage. Également dans le module itertools.all(x <= y for x, y in izip(lst, islice(lst, 1)))
.SapphireSun a tout à fait raison. Vous pouvez simplement utiliser
lst.sort()
. L'implémentation de tri de Python (TimSort) vérifie si la liste est déjà triée. Si c'est le cas, sort () se terminera en temps linéaire. Cela ressemble à une façon pythonique de s'assurer qu'une liste est triée;)la source
Bien que je ne pense pas qu'il y ait une garantie pour que la fonction
sorted
intégrée appelle sa fonction cmp aveci+1, i
, il semble le faire pour CPython.Vous pouvez donc faire quelque chose comme:
Ou de cette façon (sans instructions if -> EAFP a mal tourné? ;-)):
la source
Pas très pythonique du tout, mais nous avons besoin d'au moins une
reduce()
réponse, non?La variable d'accumulateur stocke simplement cette dernière valeur vérifiée, et si une valeur est inférieure à la valeur précédente, l'accumulateur est mis à l'infini (et sera donc toujours l'infini à la fin, car la `` valeur précédente '' sera toujours plus grande que l'actuel).
la source
Comme indiqué par @aaronsterling, la solution suivante est la plus courte et semble la plus rapide lorsque le tableau est trié et pas trop petit: def is_sorted (lst): return (sorted (lst) == lst)
Si la plupart du temps le tableau n'est pas trié, il serait souhaitable d'utiliser une solution qui n'analyse pas tout le tableau et renvoie False dès qu'un préfixe non trié est découvert. Voici la solution la plus rapide que j'ai pu trouver, elle n'est pas particulièrement élégante:
En utilisant le benchmark de Nathan Farrington, cela permet d'obtenir un meilleur runtime que d'utiliser sorted (lst) dans tous les cas, sauf lors de l'exécution sur la grande liste triée.
Voici les résultats de référence sur mon ordinateur.
trié (lst) == lst solution
Deuxième solution:
la source
Si vous voulez le moyen le plus rapide pour les tableaux numpy, utilisez numba , qui si vous utilisez conda devrait déjà être installé
Le code sera rapide car il sera compilé par numba
puis:
la source
Juste pour ajouter une autre manière (même si cela nécessite un module supplémentaire)
iteration_utilities.all_monotone
::Pour vérifier l'ordre DESC:
Il existe également un
strict
paramètre si vous devez vérifier des séquences strictement monotones (si les éléments successifs ne doivent pas être égaux).Ce n'est pas un problème dans votre cas mais si vos séquences contiennent des
nan
valeurs alors certaines méthodes échoueront, par exemple avec trié:Notez que les
iteration_utilities.all_monotone
performances sont plus rapides par rapport aux autres solutions mentionnées ici en particulier pour les entrées non triées (voir benchmark ).la source
Paresseux
la source
all(a <= b for a, b in zip(l, l[1:]))
l
est un générateur et ne prend pas en charge le découpage.Python 3.6.8
la source
Manière la plus simple:
la source
La valeur de réduction dérivée est un tuple en 3 parties de ( sortedSoFarFlag , firstTimeFlag , lastElementValue ). Il commence d' abord avec (
True
,True
,None
), qui est également utilisée comme résultat une liste vide (considérés comme classés parce qu'il n'y a pas d' éléments hors de commande). Lorsqu'il traite chaque élément, il calcule de nouvelles valeurs pour le tuple (en utilisant les valeurs de tuple précédentes avec l'élément suivant):Le résultat final de la réduction est un tuple de:
La première valeur est celle qui nous intéresse, nous utilisons donc
[0]
pour extraire cela du résultat de réduction.la source
Comme je ne vois pas cette option ci-dessus, je l'ajouterai à toutes les réponses. Notons la liste par
l
, puis:la source
Une solution utilisant des expressions d'affectation (ajoutées dans Python 3.8):
Donne:
la source
C'est en fait le moyen le plus court de le faire en utilisant la récursivité:
s'il est trié affichera True sinon affichera False
la source
RuntimeError: maximum recursion depth exceeded
pour les longues listes. Essayezany_list = range(1000)
.Celui-ci, ça va ? Simple et direct.
la source
Fonctionne définitivement en Python 3 et supérieur pour les entiers ou les chaînes:
=================================================== ====================
Une autre façon de savoir si la liste donnée est triée ou non
la source