In python, how do I test whether a list of numbers is already sorted or not?
5 Answers
This is only possible by iterating over the list (implicitly or explicitly):
all(b >= a for a, b in zip(the_list, the_list[1:])
But why not just sort it if you need it to be sorted? Python's sorting algorithm will be really cheap on an already sorted list -- possibly cheaper than the test above.
EDIT: Because this turned into a discussion about performance, here is a version using lazy iterators:
it = iter(the_list)
it.next()
all(b >= a for a, b in itertools.izip(the_list, it))
For a randomly ordered list with a million entries, this is more than 10000 times faster than the_list == sorted(the_list)
.

- 574,206
- 118
- 941
- 841
-
Indeed, this test takes about twice as long as sorting it. But testing for equality after sorting takes almost no time in comparison, so `some_list == sorted(some_list)` is a better solution in any case. – Lennart Regebro Jan 17 '11 at 07:28
-
1This is significantly faster than sorting for randomly-ordered lists. It's even faster if you use `itertools.izip` instead, especially if the test short-circuits early. Sorting will be faster if your lists are already in a predictable or pre-sorted order, since Python's sorting is good at that and this test can't short-circuit. If performance actually matters (the OP didn't say it did), then a native module could get the best of both worlds, of course. – Glenn Maynard Jan 17 '11 at 07:43
-
@Glenn, @Lennart: This obviously wasn't written with performance on big lists in mind. The additional memory it uses is at least three times the memory the initial list uses (during the the execution of `zip()`; note that `the_list[1:]` copies the list). I will add a solution using lazy iterators for completeness. – Sven Marnach Jan 17 '11 at 12:45
-
2use `next(it, None)` instead of `it.next()` to avoid StopIteration exception (empty list is a valid input (always sorted)). Micro-nitpick: `a <= b` is easier to read (at first I thought your code checks the descending order due to `>=`). – jfs Dec 01 '12 at 09:38
some_list == sorted(some_list)

- 776,304
- 153
- 1,341
- 1,358
-
7
-
2I'm sorry but this can't be the top answer. Why would you order everything just to compare the whole set when you could disprove early that something is not ordered? – Isaac Nequittepas Dec 19 '11 at 13:07
Normally you should already know if a list is sorted (because that's how your input is defined, or you previously sorted it).
If you need to verify if a list is sorted because, if it's not, you want to sort it, just sort it. It's a cheap operation if the list is already sorted, and not a lot more expensive than verifying the order explicitly.
In other words:
mylist.sort()
now you know it's sorted.

- 16,341
- 4
- 43
- 57
-
With some sorting algorithms, sorting an already-sorted list is an expensive operation. It isn't with Timsort, but obviously that is an implementation detail of Python. – Mike Graham Jan 17 '11 at 22:20
-
1It's also useful to know if a list is sorted or not for certain problem domains - you don't necessarily want the items to BE sorted, you just want to know if they are. An obvious case is writing a unit test for a sort function. :) – fluffy Dec 22 '16 at 00:37
More a comment on the other answers than an answer, but this site makes proper comments impossible.
The sort solutions are faster if the list is already partially or fully sorted. The iterative solutions are faster if the list is likely to be in random order, or if the list is out of order early on.
This is for two reasons. First, Python's sort is very good when it's given data in an order it understands (partially sorted, reversed, etc), but if the data is random or otherwise unpredictable then it can do no better than any other sort. Second, the iterative solution can short circuit doing next to no work, if it finds early on that the list is unsorted.
This shows the opposite extremes:
import timeit, random, itertools
def a(data):
return all(b >= a for a, b in itertools.izip(data, itertools.islice(data, 1, None)))
def b(data):
return data == sorted(data)
def main():
data = range(1000000)
print "Sorted, iterative:", timeit.timeit(lambda: a(data), number=10)
print "Sorted, sort:", timeit.timeit(lambda: b(data), number=10)
random.shuffle(data)
print "Random, iterative:", timeit.timeit(lambda: a(data), number=10)
print "Random, sort:", timeit.timeit(lambda: b(data), number=10)
resulting in these timings on my system:
Sorted, iterative: 1.42838597298
Sorted, sort: 0.498414993286
Random, iterative: 0.000043
Random, sort: 10.5548219681
So, at these extremes the sorting approach is about three times faster, and the linear approach is about ... two hundred thousand times faster.
Note that the real difference here is not O(n) vs. O(n log n); the difference between those complexities isn't nearly that wide. The main difference is that the linear version can short circuit as soon as it finds two values that are out of order, where the sorting version always has to do all of the work.
A native implementation could get ideal performance of both, giving O(n) complexity, the ability to short-circuit, and the low overhead of native code that makes the sorting approach faster. If (and only if!) performance really matters, that would be the correct solution.
(Note that normally I wouldn't recommend choosing a solution based on performance unless performance was actually an issue, but it's worth noting here since neither approach is that much simpler than the other. The sorting version is a little simpler to understand, but there's nothing at all complex about the iterative version either.)

- 55,829
- 10
- 121
- 131
-
+1 for the last paragraph. If performance matters then the explicit loop `for a, b in izip(data,islice(data, 1, None)):if a > b: return False` is ~50% faster than `all()` variant. – jfs Jan 17 '11 at 15:00
if L == (lambda pp=[]: reduce(lambda p, i: pp.append(reduce(lambda t, i:
(lambda t, i, j: (lambda l=[]: map(lambda x: (lambda xx=l.append(1):
t[sum(l) - 1] if sum(l) not in map(1..__radd__, (i, j)) else (t[i] if
sum(l) == j + 1 else t[j]))(), t))())(t, i, i + 1) if t[i] >= t[i + 1]
else t, xrange(len(p) - 1), p)) or pp[-1], iter(lambda: len(pp) >= 2
and list.__eq__(*pp[-2:]), True), L))():
print "yeah, it's sorted"

- 9,906
- 3
- 32
- 26
-
3what!? how is this helpful? This isnt a one-liner competition. Throw some new lines in there and some comments an you'll have code the rest of the world wouldnt mind reading. – sbartell Jan 17 '11 at 08:38
-
2@J.F. Sebastian, in case it wasn't clear, my code does a bubble sort of the list in question, and then checks to see if the result is equal to the original list. – habnabit Jan 17 '11 at 09:20
-
2Brain damage to someone trying to understand how that really works is guaranteed. Unexpected journey with debugger is even more fun! And I wish to look at the face of other developer in the group opening the code in their lovely IDE and then seeing this :))). I guess they will go after the author of such code with a bat :) – DmitrySemenov Mar 02 '16 at 22:41
-
1Downvoted because this code is very difficult to understand. SO should provide answers that are only as complex as necessary. See also the Zen of Python, #4: "Complex is better than complicated.". – András Aszódi Jul 11 '16 at 15:18
-
@user465139 I would argue that this _is_ complex, not complicated. So, I guess we agree? – habnabit Dec 22 '16 at 00:36
-
The only conceivable use I could think of for this is as a good example of how not to write Python. Or any language, really... – rschwieb Dec 08 '17 at 16:05