2

I'm trying to order the values in a dictionary. Each value is a tuple of the form (element, [element,element...]).

So if it looks like this:

{'5': (2, ['6']), '1': (3, ['4', '3']), '7': (3, ['9', '11', '12'])}

It should end up like this:

{'5': (2, ['6']), '1': (3, ['3', '4']), '7': (3, ['11', '12', '9'])}

The order is lexicographical string order, as you can see.

I tried to sort with a lambda but I cannot get to the list:

sortedDict = sorted(orderDict.values(),key=lambda x:x[0])
Zero Piraeus
  • 56,143
  • 27
  • 150
  • 160
LordNord
  • 123
  • 8

3 Answers3

3

You're almost there, what you want to do is use sorted on the 2nd element of the value with key=str (if you're not sure that your elements are always of type str already).

Also you don't need to use a lambda-expression for this.

This can simply be done using dict comprehension:

d = {'5': (2, ['6']), '1': (3, ['4', '3']), '7': (3, ['9', '11', '12'])}

sorted_d = {k: (v0, sorted(v1, key=str)) for k, (v0, v1) in d.items()}

If you want to do this in-place then the answer of @ZeroPiraeus is the recommended way. As sort is an in-place operation you could, in principle, pack this in a list comprehension. Note, however, that this is not a recommended way as you'll generate a list you're not using:

In [38]: [v1.sort(key=str) for _, v1 in d.values()]                            
Out[38]: [None, None, None]
j-i-l
  • 10,281
  • 3
  • 53
  • 70
  • Thank you very much , if it's about time complexity, there is a difference of using lambda? – LordNord Dec 22 '18 at 11:55
  • @LordNord There is no straight-forward answer to this. In some cases generators are faster, sometimes `lambda`-expressoins. This is a touchy subject in the python community, so I'll only point you to some discussions: https://stackoverflow.com/questions/3013449/list-comprehension-vs-lambda-filter https://stackoverflow.com/questions/1247486/list-comprehension-vs-map – j-i-l Dec 22 '18 at 12:18
  • 1
    Please do not use a list comprehension if you don't need the list produced. This is not idiomatic Python. Use a `for` loop instead. – timgeb Dec 22 '18 at 12:41
  • @timgeb you are right, I should have stated more clearly that the for-loop is the recommended way. Adapted the answer. – j-i-l Dec 22 '18 at 12:56
  • 1
    @jojo thank you, I'm using the Zero Piraeus , for me it looks more readable, any way thank you very much for helping me, I'v learned something new. – LordNord Dec 22 '18 at 13:20
  • @LordNord You are welcome! I understand that a for-loop looks easier to read and if you want to modify your existing dictionary and not create a new one, I also recommend you using the solutions of ZeroPiraeus. If you want to keep the original dictionary as it is and create a new, sorted one, then I'd recommend using my suggestion. Also, `list`- and `dict`- comprehension might seem hard at the beginning, but it is really useful, so I can only warmly recommend to try it out! :) – j-i-l Dec 22 '18 at 13:24
  • @jojo I should use them more, anyway they are useful, if I will get into this, It will be easier. – LordNord Dec 22 '18 at 13:27
2

If you want to return a sorted copy of orderDict, the answer by @jojo will work. To sort the dictionary in place without needing to make a copy, simply iterate over its values and sort them:

for v in orderDict.values():
    v[1].sort()

Note that you don't need to specify a key, since your lists are already made up of strings, which will be sorted as you expect. If your list did contain integers, you'd add key=str:

for v in orderDict.values():
    v[1].sort(key=str)
Zero Piraeus
  • 56,143
  • 27
  • 150
  • 160
2

Another solution is using dict.setdefault(), as follows:

my_d = {'5': (2, ['6']), '1': (3, ['4', '3']), '7': (3, ['9', '11', '12'])}
new_d ={}
for n in my_d.keys():
    new_d.setdefault(n, (my_d[n][0], sorted(my_d[n][1])))

print new_d

Output:

{'1': (3, ['3', '4']), '5': (2, ['6']), '7': (3, ['11', '12', '9'])}
Kian
  • 1,319
  • 1
  • 13
  • 23