Is there a way to check if a list is sorted either in ascending or descending order in one pass?
From this answer , I modified to also support descending order check, so my code now looks like this, is there a way to check this without having to use two for loops?
def is_sorted(check):
current = check
forwarded = check[1:]
ascending_check = all(i<=j for i, j in zip(current, forwarded))
descending_check = all(i>=j for i, j in zip(current, forwarded))
return ascending_check or descending_check
numbers = list(range(1, 10))
print(is_sorted(numbers))
reverse_numbers = list(range(10, 0, -1))
print(is_sorted(reverse_numbers))
not_sorted = [1, 3, 2, 4, 5]
print(is_sorted(not_sorted))
You can examine the first two elements, then return True
if the entire list has the same ordering as those two. You have to also take into account the possibility that there is a tie at the beginning, and that the entire list only contains the same values throughout.
def is_sorted(check):
ascending = True
descending = True
previous = check[0]
for item in check[1:]:
if ascending and item < previous:
ascending = False
if descending and item > previous:
descending = False
if not ascending and not descending:
return False
previous = item
return True
You could check pairs of consecutive elements, keep track of whether the first pair that is not ==
is <
or >
, and check that all the other pairs have the same relation (if not equal):
def is_sorted(lst):
asc = None
for i in range(len(lst)-1):
a, b = lst[i], lst[i+1]
if a == b:
continue
if asc is None:
asc = (a < b)
if (a < b) != asc:
return False
return True
That's a bit verbose, but you could also make it shorter with next
and all
, using a shared zip
iterator for both so the entire list is iterated only once.
def is_sorted(lst):
pairs = zip(lst, lst[1:])
asc = next((a < b for a, b in pairs if a != b), None)
return asc is None or all((a < b) == asc for a, b in pairs if a != b)
However, this version (like your original) will create a copy of the input list with lst[1:]
, so that's not really just a single loop, either. To fix that, you could eg use itertools.tee
or islice
.
This would work:
def is_sorted(check):
asc = desc = True
i, L = 0, len(check)
while (i < (L-1)) and (asc or desc):
if check[i] < check[i+1]:
desc = False
elif check[i] > check[i+1]:
asc = False
if not (asc or desc):
break
i += 1
if asc and desc:
return "Ascending and Descending"
elif asc:
return "Ascending"
elif desc:
return "Descending"
else:
return "Not ascending and not descending"
Tests:
print (is_sorted([1, 2, 3]))
print (is_sorted([3, 2, 1]))
print (is_sorted([1, 2, 3, 2, 1]))
print (is_sorted([1, 1, 1]))
Output:
Ascending
Descending
Not ascending and not descending
Ascending and Descending
You can try to check if sorted ascending way, if not: array[::-1]
, and check again. array[::-1]
reverses the array.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.