Sorting by Item or by Attribute
Credit: Matthew Wood
Problem
You need to sort a list of
(x, y) coordinates by item y,
or, more generally, sort a list of objects by any attribute or item.
Solution
You might first think of something like the following class, based on
the simple but slow approach of passing a comparison function to the
sort method:
class Sorter:
# Notice how _ _compare is dependent on self._ _whichindex
def _ _compare(self, x, y):
return cmp(x[self._ _whichindex], y[self._ _whichindex])
# Pass the sort function the _ _compare function defined above
def _ _call_ _(self, data, whichindex = None):
if whichindex is None :
data.sort( )
else :
self._ _whichindex = whichindex
data.sort(self._ _compare)
return data # handy for inlining, and low-costThe trick is to use a bound method that accesses instance state as the comparison function to determine which item (or attribute, but this version deals only with items) to fetch. Unfortunately, this makes the approach nonreentrant and not thread-safe.
Thanks to the faster, more robust, and more flexible DSU idiom, it’s not hard to make a more general version that allows attributes as well as items, guarantees a stable sort, is both reentrant and thread-safe, and is speedier to boot:
class Sorter: def _helper(self, data, aux, inplace): aux.sort( ) result = [data[i] for junk, i in aux] if inplace: data[:] = result return result def byItem(self, data, itemindex=None, inplace=1): if itemindex is None: if inplace: data.sort( ) result = ...