This question already has answers here:
How do I sort a dictionary by value?
(34 answers)
How to sort a Python dict's keys by value
(5 answers)
Closed 9 years ago.
I've got a dict with string keys and int values. Is there any way I could take this dict and use it to get a list of the keys from highest to lowest value?
Example:
>>> myDict = {'seven': 7, 'four': 4, 'one': 1, 'two': 2, 'five': 5, 'eight': 8}
>>> myList = myDict.sortNumericallyByKeys
>>> myList
['eight', 'seven', 'five', 'four', 'two', 'one']
sorted(myDict, key=myDict.get, reverse=True)
Here's one way of doing it:
>>> myDict = {'seven': 7, 'four': 4, 'one': 1, 'two': 2, 'five': 5, 'eight': 8}
>>> sorted(myDict.iterkeys(), key=lambda k: myDict[k], reverse=True)
['eight', 'seven', 'five', 'four', 'two', 'one']
(Inspired by this answer)
It uses the built-in function sorted (with reverse=True to get highest to lowest),
and the key argument is a function that sets the sort key. In this case it's a lambda that fetches the corresponding dict value, but it can be pretty much anything. For example, you could use operator.itemgetter(1) or myDict.get as shown by other answers, or any other sorting function (other than by value).
You can use items to get a list of pairs key-value and sorted to sort them using your criteria:
myList = sorted(myDict.items(), key=lambda x: x[1], reverse=True)
If you're using ipython, you can type myDict.tabtab and you're get a list of all functions. You can also type print myDict.items.__doc__ and get a quick documentation.
The key parameter is a function to apply to an element before it gets compared. As items returns a list of pairs and sorting is done on pairs' second element, key is a function which gets the second element from a tuple.
Of course, it is possible to get rid of the items call, using:
myList = sorted(myDict, key=myDict.get, reverse=True) #posted in another answer
Another variation:
import operator
d = {'q':2, 'x':1, 'b':10}
s = sorted(d.iteritems(), key=operator.itemgetter(1), reverse=True)
The operator module provides itemgetter which is designed to be used like this. It's faster than a lambda. ;-)
Edit:
I kinda misinterpreted the question. My solution returns a list of tuples (key, value) instead of just a list of strings.
As a bonus to make it up, have a look at collections.OrderedDict. You might also want to consider using the dict 'reversed'. e.g. switch the keys and values.
Related
#add the even values to dict to dict2
dict={"1":"one", "2":"two","3":"three","4":"four","5":"five","6":"six","7":"seven","8":"eight","9":"nine","10":"10"}
dict2={}
i want to add only the even values from the key (eg. "2":"two") to dictionary and print it.
You can use dict comprehension:
dct = {"1":"one", "2":"two","3":"three","4":"four","5":"five","6":"six","7":"seven","8":"eight","9":"nine","10":"10"}
output = {k: v for k, v in dct.items() if int(k) % 2 == 0}
print(output)
# {'2': 'two', '4': 'four', '6': 'six', '8': 'eight', '10': '10'}
Note that using dict as a custom variable name is strongly discouraged, as it overwrites the built-in function dict.
Solution 1 (Using Dictionary Comprehension)
See #j1-lee's answer
dict1 = {"1":"one", "2":"two","3":"three","4":"four","5":"five","6":"six","7":"seven","8":"eight","9":"nine","10":"10"}
dict2 = {k: v for k, v in dict1.items() if int(k) % 2 == 0}
print(dict2)
Output
{'2': 'two', '4': 'four', '6': 'six', '8': 'eight', '10': '10'}
Do keep in mind that you should avoid using dict as a variable name as #j1-lee correctly pointed out:
Note that using dict as a custom variable name is strongly discouraged, as it overwrites the built-in function dict.
You might ask, why use dictionary comprehension?
Dictionary comprehension is a powerful concept and can be used to substitute for loops and lambda functions. However, not all for loop can be written as a dictionary comprehension but all dictionary comprehension can be written with a for loop.
For loops are used to repeat a certain operation or a block of instructions in a program for a given number of times. However, nested for loops (for loop inside another for loop) can get confusing and complex. Dictionary comprehensions are better in such situations and can simplify the readability and your understanding of the code.
Solution 2 (Using filter() and lambda expressions)
You can combine the use of the filter() function with lambda expressions to solve your problem in a single line (Inspired from #THUNDER 07's answer).
Convert the dict1 items to a list that contains both the key and value pair: list(dict1.items()
Use a lambda expression for every key,value pair that:
converts the key to an int int(x[0])
and then checks if the first element x[0] in the pair is even or not (int(x[0])%2 == 0)
filter() will then add that key,value pair to the resulting dictionary
We then convert the result to a dictionary by calling dict() hence why it's better to use dict1 instead of dict for a dictionary variable name
dict1={"1":"one", "2":"two","3":"three","4":"four","5":"five","6":"six","7":"seven","8":"eight","9":"nine","10":"10"}
dict2 = dict(filter(lambda x: (int(x[0])%2 == 0), list(dict1.items())))
print(dict2)
Output
{'2': 'two', '4': 'four', '6': 'six', '8': 'eight', '10': '10'}
Why use lambda expressions?
We use lambda functions when we require a nameless function for a short period of time.
Solution 3 (Simple for loop)
A simple intuitive way to understand more what's going on would be to loop over each key in the first dictionary.
Loop over each key in the source dictionary
Convert the key to an integer: int(key)
Check if that key is even using modulo if(int(key) % 2 == 0)
One common thing to do with conditionals is to check if a number is odd or even. If a number is evenly divisible by 2 with no remainder, then it is even. You can calculate the remainder with the modulo operator
If the key is even, add the key, value pair from the first dictionary to the second dictionary dict2[key] = dict[key]
Full code below:
dict1={"1":"one", "2":"two","3":"three","4":"four","5":"five","6":"six","7":"seven","8":"eight","9":"nine","10":"10"}
dict2={}
for key in dict1.keys():
if int(key) % 2 == 0:
dict2[key] = dict1[key]
print(dict2)
Output
{'2': 'two', '4': 'four', '6': 'six', '8': 'eight', '10': '10'}
Summary
I would recommend using Solution 1 and 2 as they are more advanced, however if you want to better understand what's going on Solution 3 might be more appropriate.
You can generalize this type of problem in a simple way by looping over the keys of the first dictionary and checking if a condition is true for each key as follows:
for key in dict1.keys():
if(condition):
dict2[key] = dict1[key]
print(dict2)
So this may be a duplicate How to filter a dictionary according to an arbitrary condition function?
Ultimately it's up to you whether you use dictionary comprehension, lambda expressions or for loops, but depending on your application some solutions might be more suitable than others.
See:
For loops or dict comprehension
Difference between dict comprehension and lambda functions
I'm looking for a method to sort a list of dicts to obtain a 'natural sort order'. I have found the module natsort, but apparantly I'm not using it right to get the list of dictionaries correctly sorted. Can anyone help to find my error?
Here's my code:
from operator import itemgetter
import natsort
# Example list an dict
list = ['13h', '1h', '3h']
dict = [{'a': '13h', 'b': 3}, {'a': '1h', 'b': 1}, {'a': '3h', 'b': 0}]
# Sort the list
natsort.natsorted(list, key=lambda y: y.lower())
# Sort the dict
# Later I also want to sort on several keys, therefore the itemgetter
sorted(dic, key=itemgetter(*['a']))
You can substitute natsort.natsorted instead of sorted() in your code and it should work. Example -
natsort.natsorted(dic, key=itemgetter(*['a']))
This should return a list of dictionaries, where the elements are sorted based on value of key 'a' .
This question already has answers here:
How do I sort a dictionary by value?
(34 answers)
Closed 3 years ago.
Assume that I have a dict.
data = {1:'b', 2:'a'}
And I want to sort data by 'b' and 'a' so I get the result
'a','b'
How do I do that?
Any ideas?
To get the values use
sorted(data.values())
To get the matching keys, use a key function
sorted(data, key=data.get)
To get a list of tuples ordered by value
sorted(data.items(), key=lambda x:x[1])
Related: see the discussion here: Dictionaries are ordered in Python 3.6+
If you actually want to sort the dictionary instead of just obtaining a sorted list use collections.OrderedDict
>>> from collections import OrderedDict
>>> from operator import itemgetter
>>> data = {1: 'b', 2: 'a'}
>>> d = OrderedDict(sorted(data.items(), key=itemgetter(1)))
>>> d
OrderedDict([(2, 'a'), (1, 'b')])
>>> d.values()
['a', 'b']
From your comment to gnibbler answer, i'd say you want a list of pairs of key-value sorted by value:
sorted(data.items(), key=lambda x:x[1])
Thanks for all answers.
You are all my heros ;-)
Did in the end something like this:
d = sorted(data, key = data.get)
for key in d:
text = data[key]
Sort the values:
sorted(data.values())
returns
['a','b']
I also think it is important to note that Python dict object type is a hash table (more on this here), and thus is not capable of being sorted without converting its keys/values to lists. What this allows is dict item retrieval in constant time O(1), no matter the size/number of elements in a dictionary.
Having said that, once you sort its keys - sorted(data.keys()), or values - sorted(data.values()), you can then use that list to access keys/values in design patterns such as these:
for sortedKey in sorted(dictionary):
print dictionary[sortedKeY] # gives the values sorted by key
for sortedValue in sorted(dictionary.values()):
print sortedValue # gives the values sorted by value
Hope this helps.
You could created sorted list from Values and rebuild the dictionary:
myDictionary={"two":"2", "one":"1", "five":"5", "1four":"4"}
newDictionary={}
sortedList=sorted(myDictionary.values())
for sortedKey in sortedList:
for key, value in myDictionary.items():
if value==sortedKey:
newDictionary[key]=value
Output: newDictionary={'one': '1', 'two': '2', '1four': '4', 'five': '5'}
In your comment in response to John, you suggest that you want the keys and values of the dictionary, not just the values.
PEP 256 suggests this for sorting a dictionary by values.
import operator
sorted(d.iteritems(), key=operator.itemgetter(1))
If you want descending order, do this
sorted(d.iteritems(), key=itemgetter(1), reverse=True)
no lambda method
# sort dictionary by value
d = {'a1': 'fsdfds', 'g5': 'aa3432ff', 'ca':'zz23432'}
def getkeybyvalue(d,i):
for k, v in d.items():
if v == i:
return (k)
sortvaluelist = sorted(d.values())
sortresult ={}
for i1 in sortvaluelist:
key = getkeybyvalue(d,i1)
sortresult[key] = i1
print ('=====sort by value=====')
print (sortresult)
print ('=======================')
My question might be a little complicated to understand but here's actually the thing. I have a nested dictionary that looks like this:
dict_a = {'one': {'bird':2, 'tree':6, 'sky':1, 'TOTAL':9},
'two': {'apple':3, 'sky':1, 'TOTAL':4},
'three': {'tree':6, 'TOTAL':6},
'four': {'nada':1, 'TOTAL':1},
'five': {'orange':2, 'bird':3, 'TOTAL':5}
}
and a list:
list1 = ['bird','tree']
newlist = []
how can I check the items in list1 whether it is in the nested dictionary of dict_a and append it to the newlist? The output should look like this:
newlist = ['one','three','five']
since bird and tree happened to be in the nested dictionary of one, three and five.
What I can think of is:
for s,v in dict_a.items():
for s1,v1 in v.items():
for item in list1:
if item == s1:
newlist.append(s)
Make list1 a set and use dictionary views, and a list comprehension:
set1 = set(list1)
newlist = [key for key, value in dict_a.iteritems() if value.viewkeys() & set1]
In Python 3, use value.keys() and dict_a.items instead.
This tests if there is a set intersection between the dictionary keys and the set of keys you are looking for (an efficient operation).
Demo:
>>> dict_a = {'one': {'bird':2, 'tree':6, 'sky':1, 'TOTAL':9},
... 'two': {'apple':3, 'sky':1, 'TOTAL':4},
... 'three': {'tree':6, 'TOTAL':6},
... 'four': {'nada':1, 'TOTAL':1},
... 'five': {'orange':2, 'bird':3, 'TOTAL':5}
... }
>>> set1 = {'bird','tree'}
>>> [key for key, value in dict_a.iteritems() if value.viewkeys() & set1]
['three', 'five', 'one']
Note that dictionary ordering is arbitrary (depending on the keys used and dictionary insertion and deletion history), so the output list order may differ.
Technically speaking, you can use your list directly too (value.viewkeys() & list1 works) but making it a set states your intention more clearly.
I have an object like this:
t = {'rand_key_1': ['x'], 'rand_key_2': [13,23], 'rand_key_3': [(1)], 'rk5': [1,100,3,4,3,3]}
a dictionary with random keys (string and/or int) which ALL have a list as a value, with varying sizes.
I want to turn this dictionary into an OrderedDict which is ordered depending on the Length of the list of the dictionary items. So after ordering I want to get:
t_ordered = {'rk5': ..., 'rand_key_2': .., 'rand_key_1': .., 'rand_key_3': ..}
(if two or more items have same value, their order do not really matter.
I tried this but I am failing:
OrderedDict(sorted(d, key=lambda t: len(t[1])))
I am not experiences so excuse me if what I try is uber stupid.
What can I do?
Thank you.
You were actually very close with the sorting function you passed to sorted. The thing to note is that sorted will return an interable of the dictionaries keys in order. So if we fix your function to index the dictionary with each key:
>>> sorted(t, key=lambda k: len(t[k]))
['rand_key_3', 'rand_key_1', 'rand_key_2', 'rk5']
You can also specify that the keys are returned in reverse order and iterating directly over these keys:
>>> for sorted_key in sorted(t, key=lambda k: len(t[k]), reverse=True):
... print sorted_key, t[sorted_key]
rk5 [1, 100, 3, 4, 3, 3]
rand_key_2 [13, 23]
rand_key_3 [1]
rand_key_1 ['x']
Usually you wouldn't need to create an OrderedDict, as you would just iterate over a new sorted list using the latest dictionary data.
Using simple dictionary sorting first and then using OrderedDict():
>>> from collections import OrderedDict as od
>>> k=sorted(t, key=lambda x:len(t[x]), reverse=True)
>>> k
['rk5', 'rand_key_2', 'rand_key_3', 'rand_key_1']
>>> od((x, t[x]) for x in k)
OrderedDict([('rk5', [1, 100, 3, 4, 3, 3]), ('rand_key_2', [13, 23]), ('rand_key_3', [1]), ('rand_key_1', ['x'])])
Since an ordered dictionary remembers its insertion order, so you can do this:
OrderedDict(sorted(d.items(), key=lambda t: len(t[0])))
OrderedDict in Python is a collection that remembers the order in which items were inserted. Ordered in this context does not mean sorted.
If all you need is to get all the items in sorted order you can do something like this:
for key, value in sorted(t, key = lambda x: -len(x[0])):
# do something with key and value
However, you are still using an unsorted data structure - just iterating over it in sorted order. This still does not support operations like looking up the k-th element, or the successor or predecessor of an element in the dict.