【发布时间】:2011-06-10 07:01:39
【问题描述】:
【问题讨论】:
【问题讨论】:
这只能通过迭代列表(隐式或显式)来实现:
all(b >= a for a, b in zip(the_list, the_list[1:])
但是,如果您需要对它进行排序,为什么不直接对其进行排序呢? Python 的排序算法在已经排序的列表上会非常便宜——可能比上面的测试便宜。
编辑:因为这变成了关于性能的讨论,所以这里是一个使用惰性迭代器的版本:
it = iter(the_list)
it.next()
all(b >= a for a, b in itertools.izip(the_list, it))
对于具有一百万个条目的随机排序列表,这比 the_list == sorted(the_list) 快 10000 倍以上。
【讨论】:
some_list == sorted(some_list) 无论如何都是更好的解决方案。
itertools.izip,它会更快,尤其是在测试早期短路的情况下。如果您的列表已经处于可预测或预先排序的顺序,排序将会更快,因为 Python 的排序擅长于此,并且此测试不会短路。如果性能确实很重要(OP 没有说它确实如此),那么本机模块当然可以两全其美。
zip() 期间;注意the_list[1:] 复制了列表)。为了完整性,我将添加一个使用惰性迭代器的解决方案。
next(it, None) 而不是 it.next() 以避免 StopIteration 异常(空列表是有效的输入(始终排序))。 Micro-nitpick:a <= b 更容易阅读(起初我以为你的代码会检查降序,因为>=)。
some_list == sorted(some_list)
【讨论】:
O(n log n) 和非短路。
通常您应该已经知道列表是否已排序(因为您的输入是这样定义的,或者您之前已对其进行了排序)。
如果您需要验证列表是否已排序,因为如果不是,您想对其进行排序,只需对其进行排序。如果列表已经排序,这是一个便宜的操作,并且不会比显式验证顺序贵很多。
换句话说:
mylist.sort()
现在你知道它已经排序了。
【讨论】:
对其他答案的评论多于答案,但这个网站使正确的 cmets 成为不可能。
如果列表已经部分或完全排序,排序解决方案会更快。如果列表可能是随机顺序的,或者如果列表在早期是无序的,则迭代解决方案会更快。
这有两个原因。首先,当 Python 以它理解的顺序(部分排序、反转等)给定数据时,它的排序非常好,但如果数据是随机的或不可预测的,那么它不会比任何其他排序做得更好。其次,如果迭代解决方案很早就发现列表未排序,则它可能会短路几乎没有工作。
这显示了相反的极端:
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)
导致我的系统出现这些时间:
Sorted, iterative: 1.42838597298
Sorted, sort: 0.498414993286
Random, iterative: 0.000043
Random, sort: 10.5548219681
因此,在这些极端情况下,排序方法大约快三倍,而线性方法大约快...二十万倍。
注意这里真正的区别是不是 O(n) vs. O(n log n);这些复杂性之间的差异并没有那么大。主要区别在于,线性版本一旦发现两个乱序的值就会短路,而排序版本总是必须完成所有工作。
本机实现可以同时获得理想的性能,提供 O(n) 复杂度、短路能力以及本机代码的低开销,从而使排序方法更快。如果(且仅当!)性能真的很重要,那将是正确的解决方案。
(请注意,除非性能实际上是一个问题,否则我通常不建议根据性能选择解决方案,但这里值得注意的是,这两种方法都没有比另一种简单得多。排序版本更容易理解,但迭代版本也没有什么复杂的。)
【讨论】:
for a, b in izip(data,islice(data, 1, None)):if a > b: return False 比 all() 变体快约 50%。
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"
【讨论】: