简体   繁体   中英

ValueError: list.remove(x): x not in list python

I'm trying to sort a list from smallest to biggest integers. Unfortunately I get the error stated above when I try to run it.

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

Here is the code of 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]

Thank for helping me out!

On your first pass through the list, you find the minimum element. However, on your second pass, min is still set to the minimum element in the original list. As a result, item < min is never true, and min forever remains the minimum element of the original list. Then when you try to remove it, you can't, because you already got rid of that item on the previous pass (unless there is a tie for the minimum, in which case this will happen as soon as all those elements are removed).

To solve this, just move min = lst[0] inside the first loop, so you reset it to a valid value each time.


You've also got some other issues, which I will mention here briefly:

You never update list_len , so you'll get an error at the end of the second pass through the outer loop (when you will attempt to go beyond the length of the list). You'd also loop forever if it didn't break bist. Luckily this whole variable is unneeded: you can use len(lst) in the outer loop, and replace your inner while loop with this:

for item in lst:  # But see below regarding variable names!
    if item < min:
        min = item

This eliminates the need to track i separately and avoids any issues with the length of the list.


Next: this looks like homework, so it's probably not critical at this moment, but it's definitely worth mentioning: if I pass a list to a function called selection_sort , I would be very surprised to discover that after being sorted, my original list is now empty!! It's generally bad form to modify an input unless you're doing so explicitly (eg an in-place sort), so I highly recommend that you do all your work on a copy of the input, to avoid deleting all the content of the original:

lst_copy = lst[:]  # If `lst` contains mutable objects (e.g. other lists), use deepcopy instead!
# Do stuff with lst_copy and avoid modifying lst

Finally, you've got two variables shadowing built-in functions: sorted and min . While this will technically work, it's poor form, and it's best to get into the habit of not naming local variables the same as builtins. By convention, if it's really the best name for the object, you can just add an underscore to the name to distinguish it from the builtin: min_ and sorted_ (or maybe better, output ), for example.

If you simply want to sort the list, you can use inbuilt sort() function:

>>> lst=[-8, 8, 4, -4, -2, 2]
>>> lst.sort()
>>> lst
[-8, -4, -2, 2, 4, 8]

If you want to sort by your method, there are two slight mistakes in your code: you need to decrement lst_len every time you remove an element and reinitialize min to lst[0] . Also outer while should be while lst_len > 1 because list of length 1 is trivially sorted. Demo is given below:

>>> 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]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM