ValueError: list.remove(x):x不在列表中 Python
我正在尝试将一个整数列表从小到大排序。但是,当我运行代码时,出现了上面提到的错误。
Traceback (most recent call last):
File "lesson_4/selection_sort.py", line 24, in <module>
print selection_sort([-8, 8, 4, -4, -2, 2]) # [-8, -4, -2, 2, 4, 8]
File "lesson_4/selection_sort.py", line 14, in selection_sort
lst.remove(min)
ValueError: list.remove(x): x not in list
这是 selection_sort.py 的代码
def selection_sort(lst):
sorted = []
list_len = len(lst) # Store this now because our loop will make it
# smaller
min = lst[0]
i = 1
while list_len > 0:
while i < list_len:
item = lst[i]
if item < min:
min = item
i += 1
lst.remove(min)
sorted.append(min)
return sorted
# Test Code
print "Testing"
print selection_sort([-8, 8, 4, -4, -2, 2]) # [-8, -4, -2, 2, 4, 8]
谢谢你们的帮助!
2 个回答
如果你只是想对列表进行排序,可以直接使用内置的 sort()
函数:
>>> lst=[-8, 8, 4, -4, -2, 2]
>>> lst.sort()
>>> lst
[-8, -4, -2, 2, 4, 8]
如果你想用自己的方法来排序,你的代码里有两个小错误:每次删除一个元素时,你需要把 lst_len
减一,并且要把 min
重新设置为 lst[0]
。另外,外层的 while 循环应该是 while lst_len > 1
,因为长度为1的列表本身就是排好序的。下面是演示代码:
>>> def selection_sort(lst):
sorted = []
list_len = len(lst) # Store this now because our loop will make it
# smaller
min = lst[0]
i = 1
while list_len > 1:
while i < list_len:
item = lst[i]
if item < min:
min = item
i += 1
lst.remove(min)
list_len-=1 # decrement length of list
min=lst[0] # reinitialize min
sorted.append(min)
return sorted
>>> selection_sort([-8, 8, 4, -4, -2, 2])
[8, 4, -4, -2, 2]
在你第一次遍历列表的时候,你找到了最小的元素。但是在你第二次遍历时,min
依然保持着原始列表中的最小元素。因此,item < min
这个条件永远不会成立,min
也就一直是原始列表中的最小元素。当你尝试去移除它时,你会发现无法移除,因为你在第一次遍历时已经把那个元素去掉了(除非有多个相同的最小元素,这种情况下,一旦所有这些元素都被移除,就会出现这个问题)。
要解决这个问题,只需把 min = lst[0]
移到第一个循环里面,这样每次循环时就能把它重置为一个有效的值。
你还有一些其他问题,我在这里简单提一下:
你从来没有更新过 list_len
,所以在第二次外部循环结束时会出错(因为你会尝试超出列表的长度)。如果没有中断的话,你的循环会一直进行下去。幸运的是,这个变量其实是多余的:你可以在外部循环中使用 len(lst)
,并把内部的 while
循环替换成这个:
for item in lst: # But see below regarding variable names!
if item < min:
min = item
这样就不需要单独跟踪 i
了,也避免了与列表长度相关的问题。
接下来:这看起来像是作业,所以现在可能不是特别关键,但值得一提的是:如果我把一个列表传给一个叫 selection_sort
的函数,我会感到非常惊讶,因为在排序后,我的原始列表竟然变成了空的!!一般来说,修改输入内容是个坏习惯,除非你明确表示要这么做(比如进行原地排序),所以我强烈建议你在处理输入时,先对其进行一个 复制,以避免删除原始内容:
lst_copy = lst[:] # If `lst` contains mutable objects (e.g. other lists), use deepcopy instead!
# Do stuff with lst_copy and avoid modifying lst
最后,你有两个变量的名字和内置函数重名:sorted
和 min
。虽然这样技术上是可行的,但这并不是一个好习惯,最好养成不把局部变量命名为内置函数的习惯。按照惯例,如果这个名字确实是最合适的,你可以在名字后面加个下划线来区分,比如 min_
和 sorted_
(或者更好,使用 output
)等。