I have a dictionary, of which every key is holding a list as a value. Each list has one or more tuples with 2 items inside, one integer, one string.
Example:
my_dict = {'dict_key_1': [(100, 'string_x1234'), (95, 'string_rtx3') ..],
'dict_key_2': [(26, 'string_abc3'), (321, 'string_432fd'), ...],
'dict_key_3': [(32, 'string_232df']}
I am iterating through this dictionary, and whilst doing that through items in the list.
However, in both iterations I must have the dictionary sorted by the highest value of the first item of any tuple in the list.
So in that case, since 321 is highest, I would get dict_key_2 first, and its items would be listed starting with the tuple of which first item is 321, then 26 and so on.
I am fine with the second iteration (sorting the list of tuples) with:
sorted(data[k], reverse = True)
But I currently fail at sorting the main dictionary depending on the highest value of any tuple in the list that that key of dictionary is holding. I currently have:
for k in sorted(data, key=lambda k: sorted(data[k])[0][0]):
However, it is not working. But when I try to print sorted(data[k])[0][0]) whilst iterating, it does indeed give the first value [0] of first tuple [0] after having it ordered on the first values of all tuples in that list (data[k])
What am I doing wrong? How can I get this dictionary sorted as needed?
Thank you.
If you don't mind sorting the lists in your dict, I would recommend to do this in two passes:
for L in my_dict.itervalues():
L.sort(reverse=True)
import collections
my_sorted_dict = collections.OrderedDict((k, my_dict[k]) for k in sorted(my_dict, key=my_dict.get, reverse=True))
Use max:
for k in sorted(data, key=lambda k: max(data[k]), reverse=True):
The following snippet will give you a new sorted dictionary:
from collections import OrderedDict
my_dict = {'dict_key_1': [(100, 'string_x1234'), (95, 'string_rtx3')],
'dict_key_2': [(26, 'string_abc3'), (321, 'string_432fd')],
'dict_key_3': [(32, 'string_232df')]}
sorted_my_dict = OrderedDict(sorted(my_dict.iteritems(),
key=lambda (k, v): max(v),
reverse=True))
Related
I have a list of dictionaries with one key and one value only. Keys are always different, value is float number. How do I sort it by value?
example_list = [{'c47-d75 d75-e6b e6b-ff1 ff1-6d6 6d6-e63 e63-80c': 292.1799470129255}, {'805-7fd': 185.56518334219}, {'805-dd3 dd3-088 088-dd3 dd3-80c': 368.5010685728143}, {'805-6b5': 145.897977770909}, {'77e-805 805-7fd': 326.693786870932}, {'323-83d': 131.71963170528})
The result should be sorted by value so the first item should be
{'805-dd3 dd3-088 088-dd3 dd3-80c': 368.5010685728143}
Could you please help?
To sort the list based on the first value of the dictionary, pass a function to sorted() to extract the first value of the dictionary.
d.values() returns an iterable of the dictionary values
iter() generates an iterator of the dictionary values
Since there is only 1 dictionary value (by assumption), calling next() on the iterator returns the first (and only) value.
To sort by greatest to least value, pass the reverse=True keyword argument to sorted().
def first_value(d):
return next(iter(d.values()))
example_list = [{'c47-d75 d75-e6b e6b-ff1 ff1-6d6 6d6-e63 e63-80c': 292.1799470129255}, {'805-7fd': 185.56518334219}, {'805-dd3 dd3-088 088-dd3 dd3-80c': 368.5010685728143}, {'805-6b5': 145.897977770909}, {'77e-805 805-7fd': 326.693786870932}, {'323-83d': 131.71963170528}]
sorted_list = sorted(example_list, key=first_value, reverse=True)
print(sorted_list[0])
Here's a slightly different approach:
>>> for d in sorted(example_list, key=lambda d: max(d.values()), reverse=True):
... print(d)
...
{'805-dd3 dd3-088 088-dd3 dd3-80c': 368.5010685728143}
{'77e-805 805-7fd': 326.693786870932}
{'c47-d75 d75-e6b e6b-ff1 ff1-6d6 6d6-e63 e63-80c': 292.1799470129255}
{'805-7fd': 185.56518334219}
{'805-6b5': 145.897977770909}
{'323-83d': 131.71963170528}
This sorts by using the max() function on the values associated with each dictionary. Since there's only one value in each dictionary, it just returns that value.
Honest question, why have a list of dictionaries instead of a single dictionary with key-value pairs?
You can create a new dictionary sorted by values as follows:
{k: v for k, v in sorted(example_dict.items(), key=lambda item: item[1], reverse = True)}
Since you want the values sorted in descending order you should keep the parameter reverse = True, else for ascending order set it to False.
Let's say we have a dictionary:
m_dict = {'2011-04-01': {'asprin': (232, -7, -4, 1), 'glucose': (3, 4, -3)},
'2011-04-02': {'clb': (-7, -2, 8), 'humulin': (3, -6, -3), 'crack': (7,-5)},
'2011-04-03': {'otc': (-1, 34, -45), 'tussin': (-2, 8)} }
I'm trying to sort this dictionary in decending order based on the number of drugs a date holds, but if two dates have the same number of drugs then sort those dates in ascending order.
So, the list in this case should be: ['2011-04-02', '2011-04-01', '2011-04-03'].
I understand how to sort based on the number of drugs, but confused on how to implement another sorting condition if the number of drugs are the same.
Something like this? I'm trying to do it in a single statement using combinations of comprehension. But this doesn't apply the rule: if the number of drugs is the same for two dates, then sort those two dates in date_lst in ascending order.
date_lst = [key for key in sorted(m_dict.keys(), key = lambda item[key]): len(item[key]))
You can sort the list by a tuple of values, the length of the dictionary element (negated to sort descending) and then the key:
date_lst = [key for key in sorted(m_dict.keys(), key=lambda k: (-len(m_dict[k]), k))]
Output:
['2011-04-02', '2011-04-01', '2011-04-03']
Note that you can just use m_dict rather than m_dict.keys() since sorted operates on the keys when sorting a dict, not the values (since that's what dict returns as an iterator). So you can simplify to:
date_lst = [key for key in sorted(m_dict, key=lambda k: (-len(m_dict[k]), k))]
Try this code.
sorted_key_list = sorted(m_dict.keys(), key = lambda t:len(m_dict[t].items()))
If you want to make dictionary with order, use collections.OrderDict as follows.
from collections import OrderedDict
sorted_dic = OrderedDict()
for key in sorted_key_list:
sorted_dic[key] = m_dict[key]
answered already, just throwing in the itemgetter operator option :
from operator import itemgetter
sorted([(key,len(value))[0]
for key,value in m_dict.items()]
,key=itemgetter(1),reverse=True)
['2011-04-01', '2011-04-02', '2011-04-03']
I have a list that holds a dictionary row like this:
queue = [{1: 0.39085439023582913, 2: 0.7138416909634645, 3: 0.9871959077954673}]
I'm tryin to get it to return the smallest value along with its key, so in this case it would return
1,0.39085439023582913
I've tried using
min(queue, key=lambda x:x[1])
but that just returns the whole row like this: any suggestions? thank you!
{1: 0.39085439023582913, 2: 0.7138416909634645, 3: 0.9871959077954673}
If you want the min for each dict in the list, you can use the following list comprehension:
[min(d.items(), key=lambda x: x[1]) for d in queue]
Which for your example returns:
[(1, 0.39085439023582913)]
d.items() returns a list of tuples in the form (key, value) for the dictionary d. We then sort these tuples using the value (x[1] in this case).
If you always have your data in the form of a list with one dictionary, you could also call .items() on the first element of queue and find the min:
print(min(queue[0].items(), key=lambda x:x[1]))
#(1, 0.39085439023582913)
Yes, min(queue) will find minimum in the list and not in the enclosed dictionary
Do this:
key_of_min_val = min(queue[0], key=queue[0].get)
print((key_of_min_val , queue[0][key_of_min_val]))
you can do it through
mykey = min(queue[0], key=queue[0].get)
then just use this key and get your dictionary value
mykey, queue[0][mykey]
I have a dictionary where the keys are strings and the values are integers. I have to return a list which has the keys with smaller values first. In case of a tie, the key which comes first lexicographically is to be returned.
For example, consider a dictionary which maps names to weights.
d={'Tony':78,'Steve':88,'Bruce':68,'Thor':78,'Bob':50}
Then the resultant list should be:
['Bob','Bruce','Thor','Tony','Steve']
Since Thor comes before Tony, lexicographically.
How do I accomplish this?
If you want to break the tie by name, first sort by value then key:
from operator import itemgetter
print(list(map(itemgetter(0), sorted(d.items(), key=itemgetter(1,0)))))
['Bob', 'Bruce', 'Thor', 'Tony', 'Steve']
Or a regular list comp:
print([k for k,_ in sorted(d.items(), key=itemgetter(1, 0))])
Fairly easy:
result = sorted(d, key=lambda k: (d[k], k))
If the dict is huge, it might be worth avoiding the per-key dict lookup by iterating the items directly and using itemgetter to flip keys and values for sorting, then remove values in the result:
from operator import itemgetter
results = list(map(itemgetter(0), sorted(d.items(), key=itemgetter(1, 0))))
I'm trying to find a smart way to sort the following data structure by std:
{'4555':{'std':5656, 'var': 5664}, '5667':{'std':5656, 'var': 5664}}
Ideally like to have a sorted dictionary (bad I know), or a list of sorted tuples, but I don't know how to get the 'std' part in my lambda expression. I'm trying the following, but how should I get at the 'stdev' bit in a smart manner? Which I want to go give a list of tuples (each tuple contains index such as [(4555, 5656), (5667, 5656)].
sorted_list = sorted(sd_dict.items(), key=lambda x:x['std'])
Since sd_dict.items() returns a list of tuples, you no longer can access the elements as if it was a dictionary in the key function. Instead, the key function gets a two-element tuple with the first element being the key and the second element being the value. So to get the std value, you need to access it like this:
lambda x: x[1]['std']
But since in your example both values are identical, you don’t actually change anything:
>>> list(sorted(sd_dict.items(), key=lambda x: x[1]['std']))
[('5667', {'var': 5664, 'std': 5656}), ('4555', {'var': 5664, 'std': 5656})]
And if you just want a pair of the outer dictionary key and the std value, then you should use a list comprehension first to transform the dictionary values:
>>> lst = [(key, value['std']) for key, value in sd_dict.items()]
>>> lst.sort(key=lambda x: x[1])
>>> lst
[('5667', 5656), ('4555', 5656)]
Or maybe you want to include an int conversion, and also sort by the key too:
>>> lst = [(int(key), value['std']) for key, value in sd_dict.items()]
>>> lst.sort(key=lambda x: (x[1], x[0]))
>>> lst
[(4555, 5656), (5667, 5656)]
Each element in your input list is a tuple of (k, dictionary) items, so you need to index into that to get to the std key in the dictionary value:
sorted(sd_dict.items(), key=lambda i: i[1]['std'])
If you wanted a tuple of just the key and the std value from the dictionary, you need to pick those out; it doesn't matter if you do so before or after sorting, just adjust your sort key accordingly
sorted([(int(k), v['std']) for k, v in sd_dict.items()], key=lambda i: i[1])
or
[(int(k), v['std']) for k, v in sorted(sd_dict.items()], key=lambda i: i[1]['std'])
However, extracting the std values just once instead of both for sorting and for extraction is going to be faster.