是否有pythonic方式检查列表是否已经在ASC
或DESC
listtimestamps = [1, 2, 3, 5, 6, 7]
isttimestamps.isSorted()
之类的内容会返回True
或False
。
我想输入一些消息的时间戳列表,并检查交易是否以正确的顺序出现。
答案 0 :(得分:171)
实际上我们没有给出anijhaw正在寻找的答案。这是一个班轮:
all(l[i] <= l[i+1] for i in xrange(len(l)-1))
对于Python 3:
all(l[i] <= l[i+1] for i in range(len(l)-1))
答案 1 :(得分:64)
我会用
if sorted(lst) == lst:
# code here
除非它是一个非常大的列表,在这种情况下你可能想要创建一个自定义函数。
如果您只是对它进行排序,如果它没有排序,那么请忘记检查并对其进行排序。
lst.sort()
并且不要考虑太多。
如果您想要自定义功能,可以执行类似
的操作def is_sorted(lst, key=lambda x: x):
for i, el in enumerate(lst[1:]):
if key(el) < key(lst[i]): # i is the index of the previous element
return False
return True
如果列表已经排序,那么这将是O(n)(并且for
循环中的O(n)!),除非你期望它没有排序(并且相当随机)大多数时候,我会再次对列表进行排序。
答案 2 :(得分:36)
这个迭代器形式比使用整数索引快10-15%:
# python2 only
if str is bytes:
from itertools import izip as zip
def is_sorted(l):
return all(a <= b for a, b in zip(l, l[1:]))
答案 3 :(得分:18)
实现此目的的一种很好的方法是使用imap
中的itertools
函数:
from itertools import imap, tee
import operator
def is_sorted(iterable, compare=operator.le):
a, b = tee(iterable)
next(b, None)
return all(imap(compare, a, b))
这种实现很快,适用于任何迭代。
答案 4 :(得分:10)
我运行了基准,。这些基准测试是在MacBook Pro 2010 13“(Core2 Duo 2.66GHz,4GB 1067MHz DDR3 RAM,Mac OS X 10.6.5)上运行的。sorted(lst, reverse=True) == lst
是长列表中最快的,而all(l[i] >= l[i+1] for i in xrange(len(l)-1))
是短列表中最快的
更新:我修改了脚本,以便您可以直接在自己的系统上运行它。以前的版本有bug。另外,我添加了已排序和未排序的输入。
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))
所以在大多数情况下都有明显的赢家。
更新: aaronsterling的答案(#6和#7)实际上是所有情况下最快的。 #7是最快的,因为它没有一个间接层来查找密钥。
#!/usr/bin/env python
import itertools
import time
def benchmark(f, *args):
t1 = time.time()
for i in xrange(1000000):
f(*args)
t2 = time.time()
return t2-t1
L1 = range(4, 0, -1)
L2 = range(100, 0, -1)
L3 = range(0, 4)
L4 = range(0, 100)
# 1.
def isNonIncreasing(l, key=lambda x,y: x >= y):
return all(key(l[i],l[i+1]) for i in xrange(len(l)-1))
print benchmark(isNonIncreasing, L1) # 2.47253704071
print benchmark(isNonIncreasing, L2) # 34.5398209095
print benchmark(isNonIncreasing, L3) # 2.1916718483
print benchmark(isNonIncreasing, L4) # 2.19576501846
# 2.
def isNonIncreasing(l):
return all(l[i] >= l[i+1] for i in xrange(len(l)-1))
print benchmark(isNonIncreasing, L1) # 1.86919999123
print benchmark(isNonIncreasing, L2) # 21.8603689671
print benchmark(isNonIncreasing, L3) # 1.95684289932
print benchmark(isNonIncreasing, L4) # 1.95272517204
# 3.
def isNonIncreasing(l, key=lambda x,y: x >= y):
return all(key(a,b) for (a,b) in itertools.izip(l[:-1],l[1:]))
print benchmark(isNonIncreasing, L1) # 2.65468883514
print benchmark(isNonIncreasing, L2) # 29.7504849434
print benchmark(isNonIncreasing, L3) # 2.78062295914
print benchmark(isNonIncreasing, L4) # 3.73436689377
# 4.
def isNonIncreasing(l):
return all(a >= b for (a,b) in itertools.izip(l[:-1],l[1:]))
print benchmark(isNonIncreasing, L1) # 2.06947803497
print benchmark(isNonIncreasing, L2) # 15.6351969242
print benchmark(isNonIncreasing, L3) # 2.45671010017
print benchmark(isNonIncreasing, L4) # 3.48461818695
# 5.
def isNonIncreasing(l):
return sorted(l, reverse=True) == l
print benchmark(isNonIncreasing, L1) # 2.01579380035
print benchmark(isNonIncreasing, L2) # 5.44593787193
print benchmark(isNonIncreasing, L3) # 2.01813793182
print benchmark(isNonIncreasing, L4) # 4.97615599632
# 6.
def isNonIncreasing(l, key=lambda x, y: x >= y):
for i, el in enumerate(l[1:]):
if key(el, l[i-1]):
return False
return True
print benchmark(isNonIncreasing, L1) # 1.06842684746
print benchmark(isNonIncreasing, L2) # 1.67291283607
print benchmark(isNonIncreasing, L3) # 1.39491200447
print benchmark(isNonIncreasing, L4) # 1.80557894707
# 7.
def isNonIncreasing(l):
for i, el in enumerate(l[1:]):
if el >= l[i-1]:
return False
return True
print benchmark(isNonIncreasing, L1) # 0.883186101913
print benchmark(isNonIncreasing, L2) # 1.42852401733
print benchmark(isNonIncreasing, L3) # 1.09229516983
print benchmark(isNonIncreasing, L4) # 1.59502696991
答案 5 :(得分:9)
我会这样做(从这里偷走很多答案[Aaron Sterling,Wai Yip Tung,来自Paul McGuire的分类],主要是Armin Ronacher):
from itertools import tee, izip
def pairwise(iterable):
a, b = tee(iterable)
next(b, None)
return izip(a, b)
def is_sorted(iterable, key=lambda a, b: a <= b):
return all(key(a, b) for a, b in pairwise(iterable))
一件好事:你不必为系列实现第二个迭代(与列表切片不同)。
答案 6 :(得分:3)
SapphireSun 非常正确。您可以使用lst.sort()
。 Python的排序实现(TimSort)检查列表是否已经排序。如果是这样,sort()将在线性时间内完成。听起来像Pythonic一样确保列表被排序;)
答案 7 :(得分:3)
虽然我不认为有sorted
内置调用cmp函数i+1, i
的保证,但它似乎对CPython这样做了。
所以你可以这样做:
def my_cmp(x, y):
cmpval = cmp(x, y)
if cmpval < 0:
raise ValueError
return cmpval
def is_sorted(lst):
try:
sorted(lst, cmp=my_cmp)
return True
except ValueError:
return False
print is_sorted([1,2,3,5,6,7])
print is_sorted([1,2,5,3,6,7])
或者这种方式(没有if语句 - &gt; EAFP出错了?;-)):
def my_cmp(x, y):
assert(x >= y)
return -1
def is_sorted(lst):
try:
sorted(lst, cmp=my_cmp)
return True
except AssertionError:
return False
答案 8 :(得分:3)
根本不是Pythonic,但我们需要至少一个reduce()
答案,对吗?
def is_sorted(iterable):
prev_or_inf = lambda prev, i: i if prev <= i else float('inf')
return reduce(prev_or_inf, iterable, float('-inf')) < float('inf')
累加器变量只存储最后检查的值,如果任何值小于前一个值,则累加器设置为无穷大(因此在结束时仍然是无穷大,因为'先前值'将始终比现在更大。)
答案 9 :(得分:3)
我使用这个基于numpy.diff()的单行程序:
def issorted(x):
"""Check if x is sorted"""
return (numpy.diff(x) >= 0).all() # is diff between all consecutive entries >= 0?
我还没有真正对其他任何方法进行计时,但我认为它比任何纯Python方法都快,特别是对于大n,因为numpy.diff中的循环(可能)直接在C中运行(n-1减法)然后进行n-1次比较)。
但是,如果x是unsigned int,则需要注意,这可能会导致numpy.diff()中的静默整数下溢,从而导致误报。这是修改后的版本:
def issorted(x):
"""Check if x is sorted"""
try:
if x.dtype.kind == 'u':
# x is unsigned int array, risk of int underflow in np.diff
x = numpy.int64(x)
except AttributeError:
pass # no dtype, not an array
return (numpy.diff(x) >= 0).all()
答案 10 :(得分:3)
这与最佳答案类似,但我更喜欢它,因为它避免了显式索引。假设您的列表名称为lst
,则可以使用(item, next_item)
从列表中生成<{1}}元组:
zip
在Python 3中,all(x <= y for x,y in zip(lst, lst[1:]))
已经返回一个生成器,在Python 2中,您可以使用zip
来提高内存效率。
小演示:
itertools.izip
评估元组>>> lst = [1, 2, 3, 4]
>>> zip(lst, lst[1:])
[(1, 2), (2, 3), (3, 4)]
>>> all(x <= y for x,y in zip(lst, lst[1:]))
True
>>>
>>> lst = [1, 2, 3, 2]
>>> zip(lst, lst[1:])
[(1, 2), (2, 3), (3, 2)]
>>> all(x <= y for x,y in zip(lst, lst[1:]))
False
时,最后一个失败。
奖励:检查无法编入索引的有限(!)生成器:
(3, 2)
如果您使用的是Python 2,请确保在此使用>>> def gen1():
... yield 1
... yield 2
... yield 3
... yield 4
...
>>> def gen2():
... yield 1
... yield 2
... yield 4
... yield 3
...
>>> g1_1 = gen1()
>>> g1_2 = gen1()
>>> next(g1_2)
1
>>> all(x <= y for x,y in zip(g1_1, g1_2))
True
>>>
>>> g2_1 = gen2()
>>> g2_2 = gen2()
>>> next(g2_2)
1
>>> all(x <= y for x,y in zip(g2_1, g2_2))
False
,否则您将无法从发生器创建列表。
答案 11 :(得分:2)
如@aaronsterling所述,以下解决方案是最短的,并且在数组排序时看起来最快,而且不是太小: def is_sorted(lst): return(sorted(lst)== lst)
如果大多数情况下数组没有排序,则需要使用不扫描整个数组的解决方案,并在发现未排序的前缀后立即返回False。以下是我能找到的最快的解决方案,它不是特别优雅:
def is_sorted(lst):
it = iter(lst)
try:
prev = it.next()
except StopIteration:
return True
for x in it:
if prev > x:
return False
prev = x
return True
使用Nathan Farrington的基准测试,除了在大型排序列表上运行外,在所有情况下都比使用sorted(lst)实现更好的运行时间。
以下是我计算机上的基准测试结果。
排序(lst)== lst解决方案
第二个解决方案:
答案 12 :(得分:2)
只是添加另一种方式(即使它需要额外的模块):iteration_utilities.all_monotone
:
>>> from iteration_utilities import all_monotone
>>> listtimestamps = [1, 2, 3, 5, 6, 7]
>>> all_monotone(listtimestamps)
True
>>> all_monotone([1,2,1])
False
检查DESC订单:
>>> all_monotone(listtimestamps, decreasing=True)
False
>>> all_monotone([3,2,1], decreasing=True)
True
如果您需要严格检查(如果连续元素不应该相等)单调序列,还有一个strict
参数。
在您的情况下这不是问题,但是如果您的序列包含nan
值,那么某些方法将失败,例如使用sorted:
def is_sorted_using_sorted(iterable):
return sorted(iterable) == iterable
>>> is_sorted_using_sorted([3, float('nan'), 1]) # definetly False, right?
True
>>> all_monotone([3, float('nan'), 1])
False
请注意,与此处提到的其他解决方案相比,iteration_utilities.all_monotone
执行速度更快,特别是对于未排序的输入(请参阅benchmark)。
答案 13 :(得分:2)
如果您想要使用numpy数组的最快方法,请使用numba,如果您使用conda,则应该已经安装
代码很快,因为它将由numba编译
import numba
@numba.jit
def issorted(vec, ascending=True):
if len(vec) < 2:
return True
if ascending:
for i in range(1, len(vec)):
if vec[i-1] > vec[i]:
return False
return True
else:
for i in range(1, len(vec)):
if vec[i-1] < vec[i]:
return False
return True
然后:
>>> issorted(array([4,9,100]))
>>> True
答案 14 :(得分:1)
more_itertools.is_sorted
我不确定何时添加此内容,但尚未提及:
import more_itertools
ls = [1, 4, 2]
print(more_itertools.is_sorted(ls))
ls2 = ["ab", "c", "def"]
print(more_itertools.is_sorted(ls2, key=len))
答案 15 :(得分:1)
随着即将到来的Python 3.10
release schedule
,新的pairwise
函数提供了一种在成对的连续元素之间滑动的方法,从而确定是否所有这些元素对满足相同的排序谓词:
from itertools import pairwise
all(x <= y for x, y in pairwise([1, 2, 3, 5, 6, 7]))
# True
pairwise
的中间结果:
pairwise([1, 2, 3, 5, 6, 7])
# [(1, 2), (2, 3), (3, 5), (5, 6), (6, 7)]
答案 16 :(得分:1)
from itertools import tee
def is_sorted(l):
l1, l2 = tee(l)
next(l2, None)
return all(a <= b for a, b in zip(l1, l2))
答案 17 :(得分:0)
最简单的方法:
def isSorted(arr):
i = 1
while i < len(arr):
if(result[i] < result[i - 1]):
return False
i += 1
return True
答案 18 :(得分:0)
Python 3.6.8
from more_itertools import pairwise
class AssertionHelper:
@classmethod
def is_ascending(cls, data: iter) -> bool:
for a, b in pairwise(data):
if a > b:
return False
return True
@classmethod
def is_descending(cls, data: iter) -> bool:
for a, b in pairwise(data):
if a < b:
return False
return True
@classmethod
def is_sorted(cls, data: iter) -> bool:
return cls.is_ascending(data) or cls.is_descending(data)
>>> AssertionHelper.is_descending((1, 2, 3, 4))
False
>>> AssertionHelper.is_ascending((1, 2, 3, 4))
True
>>> AssertionHelper.is_sorted((1, 2, 3, 4))
True
答案 19 :(得分:0)
from functools import reduce
# myiterable can be of any iterable type (including list)
isSorted = reduce(lambda r, e: (r[0] and (r[1] or r[2] <= e), False, e), myiterable, (True, True, None))[0]
导出的约简值是( sortedSoFarFlag , firstTimeFlag , lastElementValue )的三部分元组。它最初以(True
,True
,None
)开头,它也用作空列表的结果(被视为已排序,因为没有乱序的元素) 。在处理每个元素时,它会计算元组的新值(将先前的元组值与下一个elementValue一起使用):
[0] (sortedSoFarFlag) evaluates true if: prev_0 is true and (prev_1 is true or prev_2 <= elementValue)
[1] (firstTimeFlag): False
[2] (lastElementValue): elementValue
减少的最终结果是一个元组:
[0]: True/False depending on whether the entire list was in sorted order
[1]: True/False depending on whether the list was empty
[2]: the last element value
第一个值是我们感兴趣的值,因此我们使用[0]
从缩减结果中获取该值。
答案 20 :(得分:0)
由于我没有在上方看到此选项,因此将其添加到所有答案中。
用l
表示列表,然后:
import numpy as np
# Trasform the list to a numpy array
x = np.array(l)
# check if ascendent sorted:
all(x[:-1] <= x[1:])
# check if descendent sorted:
all(x[:-1] >= x[1:])
答案 21 :(得分:0)
使用赋值表达式的解决方案(Python 3.8中已添加):
def is_sorted(seq):
seq_iter = iter(seq)
cur = next(seq_iter, None)
return all((prev := cur) <= (cur := nxt) for nxt in seq_iter)
z = list(range(10))
print(z)
print(is_sorted(z))
import random
random.shuffle(z)
print(z)
print(is_sorted(z))
z = []
print(z)
print(is_sorted(z))
礼物:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
True
[1, 7, 5, 9, 4, 0, 8, 3, 2, 6]
False
[]
True
答案 22 :(得分:-1)
如果它的Sorted将打印为True否则将打印出False
def is_Sorted(lst):
if len(lst) == 1:
return True
return lst[0] <= lst[1] and is_Sorted(lst[1:])
any_list = [1,2,3,4]
print is_Sorted(any_list)
答案 23 :(得分:-1)
这个怎么样?简单明了。
def is_list_sorted(al):
llength =len(al)
for i in range (llength):
if (al[i-1] > al[i]):
print(al[i])
print(al[i+1])
print('Not sorted')
return -1
else :
print('sorted')
return true
答案 24 :(得分:-2)
绝对适用于Python 3及更高版本的整数或字符串:
def tail(t):
return t[:]
letters = ['a', 'b', 'c', 'd', 'e']
rest = tail(letters)
rest.sort()
if letters == rest:
print ('Given list is SORTED.')
else:
print ('List NOT Sorted.')
=============================================== ======================
查找给定列表是否已排序的另一种方法
trees1 = list ([1, 4, 5, 3, 2])
trees2 = list (trees1)
trees2.sort()
if trees1 == trees2:
print ('trees1 is SORTED')
else:
print ('Not sorted')