asttra
asttra

Reputation: 179

Sorting a Dictionary by Key and then Value (list or tuple?)

I have a dictionary

dict = {key: [a, b, c, d]}

key is a str, a is a number, b is a number, c is a number, d is a number.

How do I print my dictionary sorted first by the number in d, and then by the length of the string in key (largest first)?

I tried using something like this...

for key in sorted(dict.items(), key=lambda x: (-len(x[0]), x[1][3])):

but I keep getting attribute errors.

Upvotes: 2

Views: 1543

Answers (5)

vash_the_stampede
vash_the_stampede

Reputation: 4606

You can keep your dictionary intact and sort it, use the dict() constructor

d = dict(sorted(d.items(), key=lambda x: (x[1][3], -len(x[0]))))
# {'stampede': [4, 2, 1, 1], 'the': [3, 3, 2, 1], 'vash': [1, 2, 3, 4]}

Upvotes: 0

NinjaKitty
NinjaKitty

Reputation: 638

Your code works, but probably not the "right" behavior you're looking for because you have the wrong negative signs. You're probably doing something wrong with your "key" variable, because when you do sorted with dict.items() it's returning you a tuple with (key, value)

This is a longshot, but my guess is that you're trying to do this?

for key in sorted(dict.items(), key=lambda x: (-len(x[0]), x[1][3])):
    print(dict[key])

This is not correct since "key" returns a tuple.

To do this in a way that's easier for you to understand, would be the following.

for key, value in sorted(d.items(), key=lambda x: (x[1][-1], -len(x[0]))):
    print(key, value)

Why does it return a list of tuples? Because dict.items() is a list of tuples, and you are sorting that list of tuples, not a dictionary object.

Upvotes: 0

TuanDT
TuanDT

Reputation: 1667

You could do something along the line of this:

>>> dictionary = {'aaaa': [1,2,2,3], 'aa': [1,2,2,3], 'aaa': [2,2,2,2], 'a': [4,2,2,6]}
>>> arr = sorted(dictionary.items(), key=lambda x: (-x[1][3],-len(x[0])))
>>> for k in arr:
        print(k)

('a', [4, 2, 2, 6])
('aaaa', [1, 2, 2, 3])
('aa', [1, 2, 2, 3])
('aaa', [2, 2, 2, 2])

Note: sort by larger d first, then longer key first.

To reverse the ordering, of any priorities, simply experimenting with removing/leaving - in the elements in the tupple in the lambda function.

Upvotes: 2

dawg
dawg

Reputation: 103754

(Shamelessly stealing jpp's example dict)

You can do:

di = {'ads': [4, 6, 1, 4], 'bs': [1, 3, 1, 9], 'cfsdg': [6, 1, 5, 4], 'ddsf': [5, 1, 6, 4]}
print('\n'.join(map(str, sorted(di.items(), key=lambda t: (t[1][-1], -len(t[0]))))))

Prints:

('cfsdg', [6, 1, 5, 4])
('ddsf', [5, 1, 6, 4])
('ads', [4, 6, 1, 4])
('bs', [1, 3, 1, 9])

Upvotes: 0

jpp
jpp

Reputation: 164623

Dictionaries are unordered collections unless you are using Python 3.6+. Therefore, I assume you want to construct an OrderedDict according to your 2 criteria. For this you can use sorted with a custom key and then feed to OrderedDict:

from collections import OrderedDict

d = {'ads': [4, 6, 1, 4], 'bs': [1, 3, 1, 9], 'cfsdg': [6, 1, 5, 4], 'ddsf': [5, 1, 6, 4]}

res = OrderedDict(sorted(d.items(), key=lambda x: (x[1][-1], -len(x[0]))))

OrderedDict([('cfsdg', [6, 1, 5, 4]),
             ('ddsf', [5, 1, 6, 4]),
             ('ads', [4, 6, 1, 4]),
             ('bs', [1, 3, 1, 9])])

Upvotes: 2

Related Questions