This may seem like a simple question but when I attempted to implement selection sort in Python, I do not get a sorted list. Is there something wrong with my implementation? The subsetting may be a problem.

source = [4,2,1,10,5,3,100]for i in range(len(source)):mini = min(source[i:]) #find minimum elementmin_index = source[i:].index(mini)-1 #find index of minimum elementsource[i:][min_index]= source[i:][0] #replace element at min_index with first elementsource[i:][0] = mini #replace first element with min elementprint source
14

Best Answer


I think there were a couple issues.

First, when your do source[i:], I believe that returns a new array of the sub-elements requested and not part of the original array, thus if you modify it, your don't modify the original. Second, you were subtracting 1 from an index when you shouldn't.

source = [4,2,1,10,5,3,100]for i in range(len(source)):mini = min(source[i:]) #find minimum elementmin_index = source[i:].index(mini) #find index of minimum elementsource[i + min_index] = source[i] #replace element at min_index with first elementsource[i] = mini #replace first element with min elementprint source

This gives:

[1, 2, 3, 4, 5, 10, 100]

Here is how I would rewrite your code. Of course in Python I would just use list.sort() to sort a list, but here is a selection sort in Python.

We make a generator expression that returns tuples of (value, i) for a value and its index from the list. Then when min() evaluates to find minimum, it finds the lowest tuple value; since the value comes first in the tuple before the index, the value will be the important part, and min() will find the lowest value. (If there is a tie, min() will use the second part of the tuple, the index, as a tie-breaker. But for sort we don't care how ties are broken.)

Now, instead of searching through the sub-list to find the min value, and then searching through it again to figure out the index, we search through it once and get both min value and index.

But we don't actually care about the min value; we care about the index. So after min() is done, we just throw away the actual value but keep the index. Adjust the index to be correct in the whole list (not in the slice of the list) and then we can swap.

We use the standard Python idiom for swapping two values. Python will build a tuple object to be the intermediate, then unpack this tuple into the left-hand-side.

lst = [4,2,1,10,5,3,100]for i_sortpos in range(len(lst)):# Make a generator expression to return (value, i) pairs.genexp = ((n, i) for i, n in enumerate(lst[i_sortpos:]))# Use genexp with min() to find lowest and its index.# (Use '_' for variable name for the actual value; we don't use it.)_, i_min = min(genexp)# Adjust index to be correct in full list.i_min += i_sortpos# Swap the number at i_sortpos with the lowest found.lst[i_sortpos], lst[i_min] = lst[i_min], lst[i_sortpos]print(lst)

EDIT: And here is a refinement of the above. A slice from a list actually allocates a new list; our code here doesn't need a new list, it just needs a convenient way to examine a sublist. The itertools module offers a function, islice(), that returns an iterator that iterates over a slice of a list. This avoids repeatedly creating and destroying lists as we examine each sublist.

I believe this is the most efficient way to do selection sort in Python. (You could get rid of the part where we bind the generator expression to the name genexp and save a few microseconds... just make the call to min() a long one-liner. But it's not really worth the loss of readability.)

import itertools as itlst = [4,2,1,10,5,3,100]for i_sortpos in range(len(lst)):# Make a generator expression to return (value, i) pairs.# Use it.islice() for to look at sublist.genexp = ((n, i) for i, n in enumerate(it.islice(lst, i_sortpos, len(lst))))# Use genexp with min() to find lowest and its index.# (Use '_' for variable name for the actual value; we don't use it.)_, i_min = min(genexp)# Adjust index to be correct in full list.i_min += i_sortpos# Swap the number at i_sortpos with the lowest found.lst[i_sortpos], lst[i_min] = lst[i_min], lst[i_sortpos]print(lst)
def selectionSort(List_):for i in range(len(List_)):`#track the current smallest valuesmallIndex = i#loop from the current smallest valuefor j in range(i+1,len(List_))if List_[j] < List_[smallIndex]:#if new value is less that our smallest value,change #smallest value to thissmallIndex = jif smallIndex != i:#swap the valuesList_[smallIndex],List_[i] = List_[i],List_[smallIndex]#return sorted listreturn List_
def ss(l): for i in range(0,len(l)):d=l.index(min(l[i:])) c=l[i]l[i]=min(l[i:])l[d]=cprint(l) #it prints each step of selection sorty=[10,9,1,5,0,6]ss(y)
def selSort(L):"""Find the smallest element in the list and put it (swap it) in the first location, Find the second element and put it (swap it) in the second locaiton, and so on. """for i in range(len(L) - 1):minIndx = iminVal= L[i]j = i + 1while j < len(L):if minVal > L[j]:minIndx = jminVal= L[j]j += 1temp = L[i]L[i] = L[minIndx]L[minIndx] = temp return L

Call:

print( selSort([120,11,0,1,3,2,3,4,5,6,7,8,9,10]) )

Output

[0, 1, 2, 3, 3, 4, 5, 6, 7, 8, 9, 10, 11, 120]
s = [1,8,4,9,3,6,2]for i in range(len(s)):maxi = max(s[0:len(s)-i]) #find max elementtempi = s.index(maxi) # find index of max elementtemp = s[len(s)-1-i] #assign last element as temps[len(s)-1-i] = maxi #put max element in last positions[tempi] = temp # put the element initially at last in its new print s 

Find the position(first and last), swap the elements if last is lower.

nums = [4,2,1,10,5,3,100]def sort(nums):###Find the position and now first 0th element is sorted and rest is unsorted#Second iteration first 2 element is sortedfor i in range(len(nums)-1):miniposition = ifor j in range(i,len(nums)):if nums[j] < nums[miniposition]:miniposition = jtemp = nums[i]nums[i] = nums[miniposition]nums[miniposition] = tempsort(nums)print (nums)

First iteration(swapped 4 and 1)[1, 2, 4, 10, 5, 3, 100]

[1, 2, 4, 10, 5, 3, 100][1, 2, 3, 10, 5, 4, 100][1, 2, 3, 4, 5, 10, 100][1, 2, 3, 4, 5, 10, 100][1, 2, 3, 4, 5, 10, 100]

Other way

nums = [4,2,1,10,5,3,100]i = 0while i<len(nums):#smallest element in the sublistsmallest = min(nums[i:])#index of smallest elementindex_of_smallest = nums.index(smallest)#swappingnums[i],nums[index_of_smallest] = nums[index_of_smallest],nums[i]i=i+1print (nums)

a slight variation of the solution provided

def selection_sort(l):i = 0while i < len(l):minium_value = min(l[i:]) # minium value at ith iterationminium_value_index = l[i:].index(minium_value) # minium value index at i th iterationif minium_value < l[i]: # if the current value already min, skipl[i + minium_value_index] = l[i] # put current value in min value's index - swap 1l[i] = minium_value # set current value with min value- swap 2i += 1return l
def selection_sort_min(): # sorting numberfor i in range(len(num)-1):current_min_index = ifor j in range(i+1,len(num)):if num[j] < num[current_min_index] :current_min_index = jnum[i],num[current_min_index] = num [current_min_index],num[i]print(num)num = [23,89,12,0,3,7,33]selection_sort_min()

here is what I think is a good way to sort a list of numbers and I hope it helps:

list=[5,4,3,1,6,8,10,9]listsorted=[]for i in range(len(list)):x=min(list)list.remove(x)listsorted.append(x)print listsorted 

and the result will be [1, 3, 4, 5, 6, 8, 9, 10]

I think the "accepted" answer here is unhelpful. If we look at e.g.

mini = min(source[i:]) #find minimum elementmin_index = source[i:].index(mini) #find index of minimum element

not only is this inefficient in terms of creating list slices unnecessarily, but they are searched unnecessarily. It's reasonably concise but I don't think it's the best solution.

def Selection_Sort(Sarray):length = len(Sarray)i = 0j = 0for i in range(length):j = i+1for j in range(length):if Sarray[i] < Sarray[j]t = Sarray[i]Sarray[i] = Sarray[j]Sarray[j] = tj = j+1i = i+1return Sarray

Code of select sort from MIT online course .

def selSort(L):for i in range(len(L) - 1):minIndx = iminVal = L[i]j = i+1while j < len(L):if minVal > L[j]:minIndx = jminVal = L[j]j += 1if minIndx != i:temp = L[i]L[i] = L[minIndx]L[minIndx] = temp
def selectSort(L):for i in range(len(L)):print LminIndex = iminValue = L[i]j = i + 1while j < len(L):if minValue > L[j]:minIndex = jminValue = L[j] j +=1temp = L[i]L[i] = L[minIndex]L[minIndex] = temp