《Think Python》第10章练习6卡住了

0 投票
6 回答
13718 浏览
提问于 2025-04-18 03:12

练习:

写一个叫做 is_sorted 的函数,这个函数接收一个列表作为参数。如果这个列表是按从小到大的顺序排列的,就返回 True,否则返回 False。你可以假设(作为前提条件)列表里的元素可以用比较运算符 <> 等进行比较。

比如, is_sorted([1,2,2]) 应该返回 True,而 is_sorted(['b', 'a']) 应该返回 False

到目前为止,我写了:

def is_sorted(stuff):
for i in stuff:
    if stuff[i+1] > stuff[i]:
        return True
    else:
        return False
        
numbers = [1, 0, 5, 2, 8]

print is_sorted(numbers)

但是每次我改变数字列表的顺序时,它似乎总是返回 True。我该怎么改才能让它正常工作呢?

6 个回答

0

我知道这个话题已经讨论很久了,但我想改进一下我的解决方案。

我想确保在一个主要是字符串的列表中,不会偷偷混入整数,或者在一个主要是整数的列表中,不会混入字符串。比如说,像这样的列表:['a', 'b', 2]

我写了一个Python程序来解决这个问题,但我觉得它有点复杂。有没有更好的解决办法呢?

def is_sorted(stuff):
    is_int = 1
    not_int = 0 

if type(stuff[0]) == int:
    of_type = is_int
else:
    of_type = not_int

for i in range(1,len(stuff)):
    if (of_type == is_int and (type(stuff[i - 1]) == int and type(stuff[i]) == int)) or \
                    (of_type == not_int and (type(stuff[i - 1]) == str and type(stuff[i]) == str)): 
        if stuff[i - 1] > stuff[i]:
            return False
    else:
        print "I saw what you did there!"
        return False
return True

print is_sorted(['b', 'a']) //False
print is_sorted(['a', 'b']) //True
print is_sorted([1, 2]) //True
print is_sorted(['a', 'b', 2]) //False; "I saw what you did there!"      
0

看起来你把 for item in stufffor i in range(len(stuff)) 混淆了。

假设 stuff = ['a', 'b', 'c', 'd']

  1. 使用 for item in stuff 时,你会一个一个地遍历 stuff 里的每个元素:'a'、'b'、'c' 和 'd'。

  2. 使用 for i in range(len(stuff)) 时,你会遍历 stuff 的每个索引:0、1、2 和 3。

需要注意的是,变量名 itemi 是这两种写法的常用名称,但并不是必须的——你可以用任何你想要的名字来替换 itemi。所以你的第二行代码 (for i in stuff) 实际上是在执行上面提到的第一个情况,而不是你期待的第二个情况。

要让你的代码执行第二个情况,你需要在第二行代码中使用 range(len(stuff)),而不是直接用 stuff

0

基于@jonrsharpe的回答,

这是一个很好的使用itertools中的pairwise方法的例子:

from itertools import tee, izip
def pairwise(iterable):
    "s -> (s0,s1), (s1,s2), (s2, s3), ..."
    a, b = tee(iterable)
    next(b, None) #or b.next() on Python 2.5 and below
    return izip(a, b)

def is_sorted(iterable):
    return all(a <= b for a,b in pairwise(iterable))

这样做可以避免使用索引访问或切片,这样你就可以在生成器上操作,显著减少内存占用。

is_sorted(xrange(5000000))

不过,不幸的是,这对像is_sorted(count(0))这样的无限生成器是没用的。

1

for i in stuff 这个写法会一个一个地遍历每个元素。如果你想要遍历的是这些元素的位置,那么你需要把循环改成

for i in range(len(stuff))

接下来,你不想在遇到比当前元素大的后续元素时就返回True。你应该在检查每一对相邻元素后再返回True,所以可以写成这样:

def is_sorted(stuff):    
    for i in range(1,len(stuff)):
        if stuff[i - 1] > stuff[i]:
           return False
    return True
3

这一行代码

for i in stuff:

是用来遍历 items,而不是 indices(索引)。如果你把 58 放在前面,就会出现 IndexError(索引错误)。而且,如果第一个项目的检查通过,你就 return(返回)了,这样太早了!你可以在 任何 项目不符合顺序时返回 False,但 所有 项目都要按顺序才能返回 True

相反,可以试着使用 enumerate 来同时获取项目和索引:

def is_sorted(stuff):
    for index, item in enumerate(stuff):
        try:
            if item > stuff[index + 1]:
                return False
        except IndexError:
            return True

另外,也可以使用 zip 来成对比较:

def is_sorted(stuff):
    return all(b >= a for a, b in 
               zip(stuff, stuff[1:]))

撰写回答