2

I have a list of dictionaries, of the form:

neighbour_list = [{1:4}, {3:5}, {4:9}, {5:2}]

I need to sort the list in order of the dictionary with the largest value. So, for the above code the sorted list would look like:

sorted_list = [{4:9}, {3:5}, {1:4}, {5:2}]

Each dictionary within the list only has one mapping.

Is there an efficient way to do this? Currently I am looping through the list to get the biggest value, then remembering where it was found to return the largest value, but I'm not sure how to extend this to be able to sort the entire list.

Would it just be easier to implement my own dict class?

EDIT: here is my code for returning the dictionary which should come 'first' in an ideally sorted list.

temp = 0
element = 0

for d in list_of_similarities:
    for k in d:
        if (d[k] > temp):
            temp = d[k]
            element = k
            dictionary = d

first = dictionary[element]
Colin Ricardo
  • 16,488
  • 11
  • 47
  • 80

2 Answers2

3

You can use an anonymous function as your sorting key to pull out the dict value (not sure if i've done this the most efficient way though:

sorted(neighbour_list, key = lambda x: tuple(x.values()), reverse=True)
[{4: 9}, {3: 5}, {1: 4}, {5: 2}]

Note we need to coerce x.values() to a tuple, since in Python 3, x.values() is of type "dict_values" which is unorderable. I guess the idea is that a dict is more like a set than a list (hence the curly braces), and there's no (well-) ordering on sets; you can't use the usual lexicographic ordering since there's no notion of "first element", "second element", etc.

maxymoo
  • 35,286
  • 11
  • 92
  • 119
3

You could list.sort using the dict values as the key.

neighbour_list.sort(key=lambda x: x.values(), reverse=1)

Considering you only have one value, for python2 you can just call next on itervalues to get the first and only value:

neighbour_list.sort(key=lambda x: next(x.itervalues()), reverse=1)
print(neighbour_list)

For python3, you cannot call next on dict.values, it would have to be:

neighbour_list.sort(key=lambda x: next(iter(x.values())), reverse=1)

And have to call list on dict.values:

neighbour_list.sort(key=lambda x: list(x.values()), reverse=1)
Padraic Cunningham
  • 176,452
  • 29
  • 245
  • 321
  • Running that, I get: `TypeError: unorderable types: dict_values() < dict_values()` – Colin Ricardo Feb 29 '16 at 23:40
  • @ColinRicardo, so you are using python3? – Padraic Cunningham Feb 29 '16 at 23:41
  • Sorry, I posted that comment before your edit! This also works, thank you. Can you just clarify what's going on here with the `next(iter(x.values()))`? – Colin Ricardo Feb 29 '16 at 23:45
  • @ColinRicardo, it pulls the only value from each dict which are used as the key to sort by, not much difference really to calling list or tuple etc.. I just added it as I had already used the next logic in the python 2 code so I wanted to add comparative code for python 3 – Padraic Cunningham Feb 29 '16 at 23:48
  • i think it's slightly more performant to coerce to tuple rather than list as in my answer – maxymoo Feb 29 '16 at 23:50
  • @maxymoo, I imagine somewhere in the nanosecond region ;) – Padraic Cunningham Feb 29 '16 at 23:54
  • 1
    @PadraicCunningham thanks for the explanation, I understand it. A quick basic time comparison using the `time` module yields the following: `0.00491786003112793` for the `tuple` method, `0.0007960796356201172` for the `iter` method, and `0.0013170242309570312` for the `list` method. – Colin Ricardo Feb 29 '16 at 23:56
  • true, nanoseconds can add up though! `next(iter(x.values())` wins anyway – maxymoo Feb 29 '16 at 23:57