确定列表是否按降序排列

时间:2012-10-04 19:09:22

标签: python

我正在尝试编写一个函数来测试列表是否按降序排列。这是我到目前为止所做的,但它似乎并不适用于所有列表。

我使用了列表[9,8,5,1,4,3,2]并返回了'true'

我似乎无法弄清楚我的错误在哪里。

def ordertest(A):
    n = len(A)
    for i in range(n):
        if A[i] >= A[i+1]:
            return 'true'
        else:
            return 'false'

7 个答案:

答案 0 :(得分:28)

您可以使用a generator expressionthe all() builtin轻松完成此操作:

all(earlier >= later for earlier, later in zip(seq, seq[1:]))

例如:

>>> seq = [9, 8, 5, 1, 4, 3, 2] 
>>> all(earlier >= later for earlier, later in zip(seq, seq[1:]))
False
>>> seq = [9, 8, 5, 4, 3, 2] 
>>> all(earlier >= later for earlier, later in zip(seq, seq[1:]))
True

这应该是好的和快速的,因为它避免了python端循环,很好地短路(如果你在2.x中使用itertools.izip()),并且很好,清晰和可读(避免循环索引,例如)。

请注意,所有迭代器(不仅仅是序列)的通用解决方案也是可能的:

first, second = itertools.tee(iterable)
next(second)
all(earlier >= later for earlier, later in zip(first, second))

答案 1 :(得分:11)

您应该进行反向检查(一旦得到A[i] < A[i+1],则返回false

def ordertest(A):
    for i in range( len(A) - 1 ):
        if A[i] < A[i+1]:
            return False
        return True

答案 2 :(得分:5)

我最初提议使用sorted,并且向我指出it may be less efficient比您的迭代更多。

>>> l = [3, 1, 2]
>>> l == sorted(l, reverse=True)
False
>>> l = [3, 2, 1]
>>> l == sorted(l, reverse=True)
True

所以我对the accepted answer,我的,Lattyware's generator solutionitertools.izip进行了基准测试。我故意使用了一个我认为有利于我的sorted解决方案的案例:一个最终只是无序的列表。这些基准测试是在旧的OpenBSD机器上的Python 2.7.1上进行的。

<强> sorted.py

import time
l = list(reversed(range(99998) + [99999, 99998]))
start = time.time()
for count in range(100):
    l == sorted(l)
end = time.time()
print('elapsed: {}'.format(end - start))

<强> walk.py

import time
def ordertest(l):
    for i in range(len(l) - 1):
        if l[i] < l[i+1]:
            return False
    return True
l = list(reversed(range(99998) + [99999, 99998]))
start = time.time()
for count in range(100):
    ordertest(l)
end = time.time()
print('elapsed: {}'.format(end - start))

<强> generator.py

import time
l = list(reversed(range(99998) + [99999, 99998]))
start = time.time()
for count in range(100):
    all(earlier >= later for earlier, later in zip(l, l[1:]))
end = time.time()
print('elapsed: {}'.format(end - start))

<强> izip.py

import itertools
import time
l = list(reversed(range(99998) + [99999, 99998]))
start = time.time()
for count in range(100):
    all(earlier >= later for earlier, later in itertools.izip(l, l[1:]))
end = time.time()
print('elapsed: {}'.format(end - start))

结果:

$ python sorted.py
elapsed: 1.0896859169
$ python walk.py
elapsed: 0.641126155853
$ python generator.py
elapsed: 4.79061508179
$ python izip.py
elapsed: 0.363445997238

正如对此答案的评论所指出的那样,zip制作列表的副本可能会使生成器表达式变慢。使用izip击败所有人。

答案 3 :(得分:5)

您可以迭代输入:

,而不是使用索引
def ordertest(iterable):
    it = iter(iterable)
    prev = next(it)
    for e in it:
        if e > prev:
            return False
        prev = e
    return True

请注意,返回字符串'true''false'是一个坏主意。相反,您可以使用Python的内置booleans

答案 4 :(得分:5)

以下是使用all()执行此测试的简明方法:

def ordertest(A):
    return all(A[i] >= A[i+1] for i in range(len(A)-1))

示例:

>>> ordertest([9,8,5,1,4,3,2])
False
>>> ordertest([9,8,5,4,3,2,1])
True

答案 5 :(得分:1)

你想做的是

n=len(A)
for i in range(n - 1):
    if A[i]<=A[i+1]:
        return 'false'
return 'true

尝试在脑海中执行您的代码。在第一次迭代中,如果A [i]大于A [i + 1]则返回true,否则返回false。你永远不会在你的名单中更进一步。

好的解决方案是测试你的情况,如果在任何时候处于假,则返回false。但如果它是正确的,这并不意味着列表的其余部分是,并且您想要测试每个值。

当您测试A [i + 1]时,您不想在列表的末尾,而是在n - 1项目的位置。

答案 6 :(得分:0)

subject

进行检查以确保没有任何错误,并且过于正确地检查使用计数器的功能是否最佳。一旦循环运行并且迭代变为1,就不再需要搜索。它将返回false,否则返回true。 谢谢!