我正在尝试编写一个函数来测试列表是否按降序排列。这是我到目前为止所做的,但它似乎并不适用于所有列表。
我使用了列表[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'
答案 0 :(得分:28)
您可以使用a generator expression和the 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 solution和itertools.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。 谢谢!