tags:

views:

73

answers:

3

I have an unsorted list of integers in a Python list. I want to sort the elements in a subset of the full list, not the full list itself. I also want to sort the list in-place so as to not create new lists (I'm doing this very frequently). I initially tried

p[i:j].sort()

but this didn't change the contents of p presumably because a new list was formed, sorted, and then thrown away without affecting the contents of the original list. I can, of course, create my own sort function and use loops to select the appropriate elements but this doesn't feel pythonic. Is there a better way to sort sublists in place?

+6  A: 

You can write p[i:j] = sorted(p[i:j])

THC4k
+1: Beat me by seconds with a simpler solution.
S.Lott
Still not what the operator desires, but what I was going to suggest. It still has to make a separate sub-array and sort it before assigning it to `p[i:j]`. I've thought for some time that there should be an option in sort() to specify the range to sort over. That would eliminate the unnecessary memory usage.
Justin Peel
That certainly addresses the "how" but wouldn't this create at least 2 new lists? One for the p[i:j] inside sorted and the second for the result from sorted.
sizzzzlerz
@sizzzzlerz: How do you know `sort()` doesn't create **O** (n log(n)) temporary lists? What's wrong with one extra list?
S.Lott
I don't know that it doesn't but there are many sorting algorithms that don't require additional memory for the main list itself and I would assume that .sort utilizes one of them. To be specific, I'm potentially calling this sort operation millions of times and I'd rather not have to continually allocate and free temporary memory.
sizzzzlerz
@sizzzzlerz: "continually allocate and free temporary memory" That's not much overhead in Python. Until you can prove this actually **is** the bottleneck, don't prematurely optimize. Indeed, creating a list that requires sorting a sublist may indicate a poor choice of algorithm which creates the list. Indeed, a list may be inappropriate when there are sublists -- you may want to consider using some kind of tree to avoid all the sorting.
S.Lott
@sizzzzlerz: What do you need this for anyways? Probably a list is not the data structure you want to begin with ...
THC4k
If you're doing tons of numeric calculations, `numpy` *might* be better.
Nick T
The list maintains a permutation of indices into another list. It is used to drive a exhaustive search for a set of solutions to a particular geometric puzzle. Once all the solutions are found for a given permutation, the next permutation of the list is found and the search proceeds until no more permutations are left. The permutation algorithm I'm using requires this sort operation. Although there are optimizations in place so I don't have to try all the possible 12! permutations, there still can be a very large number of them, thus, the desire to limit memory allocations, copies, etc..
sizzzzlerz
@sizzzzlerz: Why aren't you using `itertools`? http://docs.python.org/library/itertools.html#itertools.permutations might do this for you.
S.Lott
One of my optimizations to reduce the search space requires an ability to skip permutations that can't ever lead to a solution. This means that I may want to start my search for the next permutation at a location somewhere in the middle. itertools produces every possible permutation in lexographical order which isn't what I want.
sizzzzlerz
@sizzzzlerz: It sounds like a "flat" list is inappropriate. If you can eliminate some permutations, it sounds like you have more structure in the problem, and should perhaps be using a tree of lists where all permutations make sense.
S.Lott
A: 

"in place" doesn't mean much. You want this.

p[i:j] = list( sorted( p[i:j] ) ) 
S.Lott
A: 

This is because p[i:j] returns a new list. I can think of this immediate solution:

l = p[i:j]
l.sort()
a = 0
for x in range(i, j):
    p[x] = l[a]
    a += 1
inspectorG4dget
You could just write `p[i:j] = l`
KennyTM