0

I am trying to rank a list of dictionaries based on a common criteria. So my list looks something like this:

d = [{'key1': 0, 'key2': 1}, {'key1': 1, 'key2': 0}]

I want to obtain the rank (in reverse order) of each dictionary according to a criteria that I may specify. So, if the criteria is 'key1', the output should be:

1 0

If the criteria is 'key2', then the output should be:

0 1

I tried the following function:

def rank_simple(list, criteria):
    return sorted(range(len(list)), reverse = True, key = type(list).__getitem__(list)[criteria])

which gives the error:

TypeError: __getitem__() takes exactly one argument (0 given)

and

def rank_simple(list, criteria):
    return sorted(range(len(list)), reverse = True, key = list.__getitem__[criteria])

which gives the error:

TypeError: 'builtin_function_or_method' object has no attribute '__getitem__'

as per suggestions in Efficient method to calculate the rank vector of a list in Python

How should I solve this problem. Please note that I do not want to use scipy or numpy for this (if possible)

Community
  • 1
  • 1
akhiljain
  • 621
  • 1
  • 9
  • 18

2 Answers2

1

The problem with your approach is that you try to pass a computed value to the key argument to sorted, whereas you need to pass a function that accepts one argument (each of the items to be sorted in turn) and computes the sort key from each item:

def rank_simple(list, criteria):
    return [index for index, value in sorted(enumerate(list), reverse = True, key = lambda item: item[1][criteria])]

Also, you got the usage of __getitem__ wrong; either you access a dictionary item using [], or you use the __getitem__ call.

Thomas Lotze
  • 5,153
  • 1
  • 16
  • 16
  • `def rank_simple(list, criteria): return sorted(range(len(list)), reverse = True, key = lambda x: x[criteria]) d = [{'key1': 0, 'key2': 1},{'key1': 1, 'key2': 0}] print rank_simple(d, 'key1')` – akhiljain Mar 14 '16 at 13:15
  • This gives me the error `TypeError: 'int' object has no attribute '__getitem__'` – akhiljain Mar 14 '16 at 13:16
  • I'm sorry, got carried away by editing... I've updated to post now. – Thomas Lotze Mar 14 '16 at 13:21
1
def rank(data,key):
    # Make a list or ranks to be sorted
    ranks = [x+1 for x in xrange(len(data))]
    # Sort ranks based on the key of data each refers to
    return sorted(ranks, reverse=True, key=lambda x:data[x-1][key])
Scott Hunter
  • 48,888
  • 12
  • 60
  • 101