0

I can't figure out why the python program produces the following output:

c:\Python Programs>selection_sort.py

[7, 4, 2, 9, 6]

[2, 4, 7, 9, 6]
[2, 6, 7, 9, 4]
[2, 6, 4, 9, 7]
Traceback (most recent call last):
  File "J:\Python Programs\Python Practice\selection_sort.py", line 11, in <modu
le>
    num_list[i], num_list[min_num] = num_list[min_num], num_list[i]
IndexError: list index out of range

c:\Python Programs>

I think I understand the list index out of range part, but I'm not sure about why the 6 becomes the second element when i = 1. Didn't the machine read my if statement?

Here is the code below:

num_list = [7,4,2,9,6]
len_num_list = len(num_list)
print num_list
print""#print empty string to separate the original list from the following iterations 
for i in range(0,len_num_list):
    min_num = min(num_list[i:]) #finds minimum number in list to the right of i
    if min_num>num_list[i]:
        min_num = num_list[i]
    num_list[i], num_list[min_num] = num_list[min_num], num_list[i]
    print num_list  

2 Answers 2

1

First, let's note that in your snippet:

min_num = min(num_list[i:]) #finds minimum number in list to the right of i
if min_num>num_list[i]:
    min_num = num_list[i]

the if will never, ever match -- since min_num is the minimum of a sub-list that starts with num_list[i], it can't possibly, ever, under any circumstance, be greater than the latter.

So, lose the last two of these three statements -- they're about as useful as checking if 2+2 != 4::-).

Next, let's note that you don't really want min_num to be a value (which is what your call to min gives you) -- you want it to be an index into the list, in order to perform the swap:

num_list[i], num_list[min_num] = num_list[min_num], num_list[i]

But trying to turn a value into an index via the index method is quite an iffy path: if the input list can have any duplicates, index will always locate the first one of them, and that might quite possibly tangle you up. I personally would choose not to go there.

Rather consider the more direct path of finding the minimum index using the corresponding value via the key= feature of min! I.e:

for i in range(0,len_num_list):
    min_ind = min(range(i, len_num_list),
                  key=lambda j: num_list[j])
    num_list[i], num_list[min_ind] = num_list[min_ind], num_list[i]
    print num_list

If you're not familiar with the key= feature of many Python built-ins (min, max, sorted, ...), it's really a good thing to learn.

It sorts (or gives the min, or max, or) a certain sequence, with the comparisons done after passing each item of the sequence through the "key extraction function" you pass as key=. Here, you want "the index of the minimum" and you get that by picking the min index with a key= of the corresponding look-up of each index into the list.

I personally dislike lambda and might use key=numlist.__getitem__, but that's not very readable either -- most readable is always to use def (and I'd do the same for that swap functionality), e.g...:

def item_in_list(index): return num_list[index]
def swap(i, j): num_list[i], num_list[j] = num_list[j], num_list[i]
for i in range(0,len_num_list):
    min_ind = min(range(i, len_num_list), key=item_in_list)
    swap(i, min_ind)
    print num_list

which I find to be the most readable and elegant approach to this task.

Sign up to request clarification or add additional context in comments.

Comments

0

The problem is that min(num_list[i:]) returns a number from the list, not an index into that list. You can use the index method to get the index corresponding to min(num_list[i:]). Thus, try:

num_list = [7,4,2,9,6]
len_num_list = len(num_list)
print num_list
print""#print empty string to separate the original list from the following iterations_
for i in range(0,len_num_list):
    min_num = min(num_list[i:]) #finds minimum number in list to the right of i
    j = num_list.index(min_num)
    if min_num>num_list[i]:
        min_num = num_list[i]
    num_list[i], num_list[j] = num_list[j], num_list[i]
    print num_list

This produces the output:

[7, 4, 2, 9, 6]

[2, 4, 7, 9, 6]
[2, 4, 7, 9, 6]
[2, 4, 6, 9, 7]
[2, 4, 6, 7, 9]
[2, 4, 6, 7, 9]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.