Hello everyone,

I'm learning Python and I have a few questions about Dictionaries and sorting them by a value other than the key.

Lets say, for example, I have a Dictionary full of data that needs to be sorted on the 3rd value instead of the key. How would I go about doing this? I have tried just the .sort() and that just sorts by the key.

So if,

Data = [('1023', ['Name', '3.1', 'SomeData']), ('1000', )

how would I sort "Data" by the value where 3.1 is?

Please forgive my lack of correct terminology if I am missing some somewhere! Any help would be greatly appreciated.

It doesn't look like you're using a dictionary. It appears that you have a list of tuples, and each tuple consists of a string and a list.

I can't think of a built in way to do this. You might have to look at writing your own version of a bubble sort or something. To do that, you would go through the entire outer list and compare the 2nd element of the inner list. If they are not in the correct order, then switch them around. Repeat until you can go through the whole list without having to make any switches.

You can use the 'key' argument to 'sort' or 'sorted'. Here, Data is a list. You can write

def my_key(item):
    return item[1][1] # this returns 3.1 if item is ('1023', ['Name', '3.1', 'SomeData'])

Data.sort(key = my_key)

Data is easily turned into a dictionary:

Data = dict(Data)
L = sorted(Data.items(), key = my_key)

Similar to Gribouillis' code, but uses lambda as a helper function ...

# sort a more complex combination of lists/tuples:
mylist = [
(1, ['a', '3.1', 'ad']),
(2, ['b', '4.0', 'bd']),
(3, ['c', '2.5', 'cd']),
]
# sort by item at index [1][1] of each tuple
# using a helper function like lambda
newlist = sorted(mylist, key=lambda tup: tup[1][1])

print newlist

"""my result (made pretty) -->
[
(3, ['c', '2.5', 'cd']),
(1, ['a', '3.1', 'ad']), 
(2, ['b', '4.0', 'bd'])
]
"""

You can also use a somewhat older concept of sorting, the Schwartzian transform algorithm. This is made very easy with Python's list comprehension ...

# sort a more complex combination of lists/tuples:
    
mylist = [
(1, ['a', '3.1', 'ad']),
(2, ['b', '4.0', 'bd']),
(3, ['c', '2.5', 'cd']),
]

# use the Schwartzian transform algorithm
# temporarily put a copy of indexed item in front
templist = [(x[1][1], x) for x in mylist]
templist.sort()
# remove temporary front item after sorting
newlist = [val for (temp, val) in templist]

print newlist

"""my result (made pretty) -->
[
(3, ['c', '2.5', 'cd']),
(1, ['a', '3.1', 'ad']), 
(2, ['b', '4.0', 'bd'])
]
"""

Edited 7 Years Ago by vegaseat: n/a

I've tried all three of these methods, however, I haven't been able to get them to work correctly for my particular set of data. I believe I may have pasted my dictionary incorrectly.

Here is what I have in my dictionary:
data = {'1234': , '1000': , '1023': , '1001': , '9000': }

Would this have affected the methods of sorting that were mentioned?

Edited 7 Years Ago by xm1014: n/a

So you have a dictionary after all!

Dictionaries are indexed by key and the keys are in a hash order for fast lookups. They will always display in this order! If you want to sort by a certain item, you have to convert them to lists. I thought that is what you did.

data_dict = {
'1234': ['Matt', '2.5', 'CS'], 
'1000': ['John', '4.0', 'Music'], 
'1023': ['Aaron', '3.1', 'PreMed'], 
'1001': ['Paul', '3.9', 'Music'], 
'9000': ['Kris', '3.5', 'Business']
}

# convert dictionary to a list of tuples
data_list = [(key, val) for key, val in data_dict.items()]

print(data_list)
"""the raw list -->
[
('1234', ['Matt', '2.5', 'CS']), 
('9000', ['Kris', '3.5', 'Business']), 
('1001', ['Paul', '3.9', 'Music']), 
('1023', ['Aaron', '3.1', 'PreMed']), 
('1000', ['John', '4.0', 'Music'])
]
"""

# now you can sort the list by item[1][1]
sorted_list = sorted(data_list, key=lambda tup: tup[1][1])

print(sorted_list)
"""result sorted by item[1][1] -->
[
('1234', ['Matt', '2.5', 'CS']), 
('1023', ['Aaron', '3.1', 'PreMed']), 
('9000', ['Kris', '3.5', 'Business']), 
('1001', ['Paul', '3.9', 'Music']), 
('1000', ['John', '4.0', 'Music'])]
"""

# however if you go back to a dictionary
new_dict = dict(sorted_list)

print(new_dict)
"""result is the dictionary order again -->
{
'1234': ['Matt', '2.5', 'CS'], 
'1000': ['John', '4.0', 'Music'], 
'1001': ['Paul', '3.9', 'Music'], 
'1023': ['Aaron', '3.1', 'PreMed'], 
'9000': ['Kris', '3.5', 'Business']}
"""

So, if you want to do any processing that needs a sorted order, to have to convert your dictionary to a temporary list.

Edited 7 Years Ago by vegaseat: n/a

Ah ha! That worked! Now, since you're putting it in a list to sort the values, is there also a way to separate those values you are sorting on into a list by themselves?

Ah ha! That worked! Now, since you're putting it in a list to sort the values, is there also a way to separate those values you are sorting on into a list by themselves?

Is this what you mean?

>>> my_dict = {'a':1, 'b':2, 'c':3}
>>> my_dict.keys()
['a', 'c', 'b']
>>> my_dict.values()
[1, 3, 2]
>>>

Is this what you mean?

>>> my_dict = {'a':1, 'b':2, 'c':3}
>>> my_dict.keys()
['a', 'c', 'b']
>>> my_dict.values()
[1, 3, 2]
>>>

Not exactly, I'd like to take the values that are being sorted on and put them into a new list/dict etc.

For example, extracting only these values from the dictionary above:
new_list = ('2.5','3.5','3.9','4.0','3.1')

Not exactly, I'd like to take the values that are being sorted on and put them into a new list/dict etc.

For example, extracting only these values from the dictionary above:
new_list = ('2.5','3.5','3.9','4.0','3.1')

Okay... how about this:

>>> data_dict = {
... '1234': ['Matt', '2.5', 'CS'], 
... '1000': ['John', '4.0', 'Music'], 
... '1023': ['Aaron', '3.1', 'PreMed'], 
... '1001': ['Paul', '3.9', 'Music'], 
... '9000': ['Kris', '3.5', 'Business']
... }
>>> [data[1] for data in data_dict.values()]
['2.5', '3.5', '3.9', '3.1', '4.0']
>>>

That's just a quick list comprehension that will extract the second element (at index 1) from each list (which is stored as the "value" part of each dictionary entry.

Hah, this thread nudged me in studying more on sorting (more complex data structures) with Python. So I took a swing at it. These are the ones I came up with:

data = {'1234': ['Matt', '2.5', 'CS'],
        '1000': ['John', '4.0', 'Music'],
        '1023': ['Aaron', '3.1', 'PreMed'],
        '1001': ['Paul', '3.9', 'Music'],
        '9000': ['Kris', '3.5', 'Business']}

# Sort by name, print keys only.
print sorted(data, key=lambda x: data[x][0])

# Sort by name, print keys and values.
a = sorted(data, key=lambda x: data[x][0])
for i in a:
    print i, '->', data[i]

# Sort by name, print values only.
print map(data.get, sorted(data, key=lambda x: data[x][0]))

# Sort by names, print keys and values.
print ["%s -> %s" % (i, data.get(i)) for i in sorted(data, key=lambda x: data[x][0])]

These all sort by name, but you can change the 0 to 1 to sort by the GPA (at least that is what I think it is), and change it to 2 to sort by category/group (or whatever it is). I actually worked on this for at least an hour (maybe more, kind of lost track of time), just kept finding additional information or more interesting python methods.

The nice thing about Xydric's approach is that it doesn't lose the important connectivity with the original dictionary via the keys ...

data = {
'1234': ['Matt', '2.5', 'CS'],
'1000': ['John', '4.0', 'Music'],
'1023': ['Aaron', '3.1', 'PreMed'],
'1001': ['Paul', '3.9', 'Music'],
'9000': ['Kris', '3.5', 'Business']
}

# sort by index in value, here GPA values at index 1
# gives a list of keys in that specified order
key_list = sorted(data, key=lambda x: data[x][1])

gpa_list = [data[key][1] for key in key_list]

print( gpa_list )  # ['2.5', '3.1', '3.5', '3.9', '4.0']

# now if you wanted to know who got the 2.5
# it should be the first key in the key_list too (at index=0)
print( data[key_list[0]] )     # ['Matt', '2.5', 'CS']
# or ...
print( data[key_list[0]][0] )  # Matt

Edited 7 Years Ago by vegaseat: too

The nice thing about Xydric's approach is that it doesn't lose the important connectivity with the original dictionary via the keys ...

data = {
'1234': ['Matt', '2.5', 'CS'],
'1000': ['John', '4.0', 'Music'],
'1023': ['Aaron', '3.1', 'PreMed'],
'1001': ['Paul', '3.9', 'Music'],
'9000': ['Kris', '3.5', 'Business']
}

# sort by index in value, here GPA values at index 1
# gives a list of keys in that specified order
key_list = sorted(data, key=lambda x: data[x][1])

gpa_list = [data[key][1] for key in key_list]

print( gpa_list )  # ['2.5', '3.1', '3.5', '3.9', '4.0']

# now if you wanted to know who got the 2.5
# it should be the first key in the key_list too (at index=0)
print( data[key_list[0]] )     # ['Matt', '2.5', 'CS']
# or ...
print( data[key_list[0]][0] )  # Matt

I couldn't get the syntax on the print (data[key_list[0]) to work, should there be another "]" there?

Also, could you use this method, for example, to search by "major"? So if you wanted a list of 'Music', how would you go about this?

I couldn't get the syntax on the print (data[key_list[0]) to work, should there be another "]" there?

Also, could you use this method, for example, to search by "major"? So if you wanted a list of 'Music', how would you go about this?

If you look at my code with a sharp eye you will find that all [] match.

On part 2 ...

# sorted() handles dictionaries directly
# for indexed sorting

data = {
'1234': ['Matt', '2.5', 'CS'],
'1000': ['John', '4.0', 'Music'],
'1023': ['Aaron', '3.1', 'PreMed'],
'1001': ['Paul', '3.9', 'Music'],
'9000': ['Kris', '3.5', 'Business']
}

# sort by index in value, here by 'Major' at index 2
# gives a list of keys in that specified order
key_list = sorted(data, key=lambda x: data[x][2])

major_list = [data[key][2] for key in key_list]

print( major_list )  # ['Business', 'CS', 'Music', 'Music', 'PreMed']

# optionally create a sub dictionary of all the music majors
music_major_dict = dict([(key, data[key]) \
    for key in key_list if data[key][2] == 'Music'])

print( music_major_dict )
"""
{'1001': ['Paul', '3.9', 'Music'], '1000': ['John', '4.0', 'Music']}
"""
This question has already been answered. Start a new discussion instead.