I have the following Python array of dictionaries:
myarr = [ { \'name\': \'Richard\', \'rank\': 1 },
{ \'name\': \'Reuben\', \'rank\': 4 },
{ \'name\': \'Reece\'
You're myarr
binding here doesn't look like valid Python code (and doesn't execute in my interpreter session.
Rendering that into:
myarr = {
'Richard': 1,
'Reuben': 4,
'Reece': 0,
'Rohan': 3,
'Ralph': 2,
'Raphael': 0,
'Robin': 0 }
Gives me something on which I could base an answer.
The recommended way to do custom sorting in Python is to use the DSU (decorate, sort, undecorate) pattern. If you want to sort a dictionary by values then that looks something like:
keys_sorted_by_val = [ x[1] for x in sorted([(v,k) for k,v in myarr.items()])]
... where (v,k) for k,v in myarr.items()
is the expression to decorate; sorted()
is, obviously, the sort and the outer x[1] for x in ...
is the final undecorate step.
Obviously this might seem like a sufficiently common requirement that one might which to wrap this up in a function:
def dict_by_values(d):
return [ x[1] for x in sorted([(v,k) for k,v in d.items()])]
If you had a collection of object instances that you want to sort by some attribute you can use something like this:
def sort_by_attr(attr, coll):
results = list()
for each in coll:
assert hasattr(each, attr)
results.append((getattr(each, attr), each))
results.sort()
return [x[1] for x in results]
So if we created a class representing your name/rank data like this:
class NameRanking(object):
def __init__(self, name, rank):
self.name = name
self.rank = rank
def __repr__(self):
return "%s: %s, %s" %(self.__class__, self.name, self.rank)
... and instantiate a list of those using myarr
:
name_rankings = [ NameRanking(k, v) for k,v in myarr.items() ]
... then we could get a sorted copy of that using:
names_rankings_by_rank = sort_by_attr('rank', name_rankings)
(Yes the assert
isn't a good idea here; that's where you would put in your own exception handling or throwing code as appropriate to your application).
I'd do
sortedlist = sorted([x for x in myarr if x['rank']], key=lambda x: x['rank']) + [x for x in myarr if not x['rank']]
bit I guess it could be compressed somehow.