ValueError: list.remove(x):x不在列表中 Python

1 投票
2 回答
7407 浏览
提问于 2025-04-30 17:37

我正在尝试将一个整数列表从小到大排序。但是,当我运行代码时,出现了上面提到的错误。

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 个回答

0

如果你只是想对列表进行排序,可以直接使用内置的 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]
3

在你第一次遍历列表的时候,你找到了最小的元素。但是在你第二次遍历时,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

最后,你有两个变量的名字和内置函数重名:sortedmin。虽然这样技术上是可行的,但这并不是一个好习惯,最好养成不把局部变量命名为内置函数的习惯。按照惯例,如果这个名字确实是最合适的,你可以在名字后面加个下划线来区分,比如 min_sorted_(或者更好,使用 output)等。

撰写回答