This is how I would rewrite your code. Of course, in Python, I would just use list.sort() to sort the list, but here is sorting in Python.
We create a generator expression that returns tuples (value, i) for the value and its index from the list. Then, when min() evaluates the minimum search, it finds the smallest tuple value; since the value first goes into the tuple before the index, the value will be the important part, and min() will find the lowest value. (If there is a connection, min() will use the second part of the tuple, the index, as a tie-breaker. But for sorting, we don’t care how the connections are broken.)
Now, instead of searching the sub-list to find the value of min, and then look again at it to find out the index, we look at it once and get both the minimum value and the index.
But we really don't care about the minimum value; we care about the index. Thus, after executing min() we simply discard the actual value, but save the index. Correct the index that will be correct in the whole list (and not in the list fragment), and then we can swap them.
We use the standard Python idiom to replace two values. Python will build the tuple object in between, and then unzip that tuple to the left.
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 the clarification above. A slice from a list actually selects a new list; our code here does not need a new list, it just needs a convenient way to study subscriptions. The itertools module offers the islice() function, which returns an iterator that iterates over a list fragment. This avoids the multiple creation and destruction of lists when considering each sublist.
I believe this is the most efficient way to do sorting in Python. (You can get rid of the part where we bind the generator expression to genexp and save a few microseconds ... just make the min() call long one-line. But it's really not worth the loss of readability.)
import itertools as it lst = [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)