sort dict by value python [duplicate] - python

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 ('=======================')

Related

How do i sort a dictionnary by a custom order of values [duplicate]

I'm working on python 3.2.2.
Breaking my head more than 3 hours to sort a dictionary by it's keys.
I managed to make it a sorted list with 2 argument members, but can not make it a sorted dictionary in the end.
This is what I've figured:
myDic={10: 'b', 3:'a', 5:'c'}
sorted_list=sorted(myDic.items(), key=lambda x: x[0])
But no matter what I can not make a dictionary out of this sorted list. How do I do that? Thanks!
A modern and fast solution, for Python 3.7. May also work in some interpreters of Python 3.6.
TLDR
To sort a dictionary by keys use:
sorted_dict = {k: disordered[k] for k in sorted(disordered)}
Almost three times faster than the accepted answer; probably more when you include imports.
Comment on the accepted answer
The example in the accepted answer instead of iterating over the keys only - with key parameter of sorted() or the default behaviour of dict iteration - iterates over tuples (key, value), which suprisingly turns out to be much slower than comparing the keys only and accessing dictionary elements in a list comprehension.
How to sort by key in Python 3.7
The big change in Python 3.7 is that the dictionaries are now ordered by default.
You can generate sorted dict using dict comprehensions.
Using OrderedDict might still be preferable for the compatibility sake.
Do not use sorted(d.items()) without key.
See:
disordered = {10: 'b', 3: 'a', 5: 'c'}
# sort keys, then get values from original - fast
sorted_dict = {k: disordered[k] for k in sorted(disordered)}
# key = itemgetter - slower
from operator import itemgetter
key = itemgetter(0)
sorted_dict = {k: v for k, v in sorted(disordered.items(), key=key)}
# key = lambda - the slowest
key = lambda item: item[0]
sorted_dict = {k: v for k in sorted(disordered.items(), key=key)}
Timing results:
Best for {k: d[k] for k in sorted(d)}: 7.507327548999456
Best for {k: v for k, v in sorted(d.items(), key=key_getter)}: 12.031082626002899
Best for {k: v for k, v in sorted(d.items(), key=key_lambda)}: 14.22885995300021
Best for dict(sorted(d.items(), key=key_getter)): 11.209122000000207
Best for dict(sorted(d.items(), key=key_lambda)): 13.289728325995384
Best for dict(sorted(d.items())): 14.231471302999125
Best for OrderedDict(sorted(d.items(), key=key_getter)): 16.609151654003654
Best for OrderedDict(sorted(d.items(), key=key_lambda)): 18.52622927199991
Best for OrderedDict(sorted(d.items())): 19.436101284998585
Testing code:
from timeit import repeat
setup_code = """
from operator import itemgetter
from collections import OrderedDict
import random
random.seed(0)
d = {i: chr(i) for i in [random.randint(0, 120) for repeat in range(120)]}
key_getter = itemgetter(0)
key_lambda = lambda item: item[0]
"""
cases = [
# fast
'{k: d[k] for k in sorted(d)}',
'{k: v for k, v in sorted(d.items(), key=key_getter)}',
'{k: v for k, v in sorted(d.items(), key=key_lambda)}',
# slower
'dict(sorted(d.items(), key=key_getter))',
'dict(sorted(d.items(), key=key_lambda))',
'dict(sorted(d.items()))',
# the slowest
'OrderedDict(sorted(d.items(), key=key_getter))',
'OrderedDict(sorted(d.items(), key=key_lambda))',
'OrderedDict(sorted(d.items()))',
]
for code in cases:
times = repeat(code, setup=setup_code, repeat=3)
print(f"Best for {code}: {min(times)}")
dict does not keep its elements' order. What you need is an OrderedDict: http://docs.python.org/library/collections.html#collections.OrderedDict
edit
Usage example:
>>> from collections import OrderedDict
>>> a = {'foo': 1, 'bar': 2}
>>> a
{'foo': 1, 'bar': 2}
>>> b = OrderedDict(sorted(a.items()))
>>> b
OrderedDict([('bar', 2), ('foo', 1)])
>>> b['foo']
1
>>> b['bar']
2
I don't think you want an OrderedDict. It sounds like you'd prefer a SortedDict, that is a dict that maintains its keys in sorted order. The sortedcontainers module provides just such a data type. It's written in pure-Python, fast-as-C implementations, has 100% coverage and hours of stress.
Installation is easy with pip:
pip install sortedcontainers
Note that if you can't pip install then you can simply pull the source files from the open-source repository.
Then you're code is simply:
from sortedcontainers import SortedDict
myDic = SortedDict({10: 'b', 3:'a', 5:'c'})
sorted_list = list(myDic.keys())
The sortedcontainers module also maintains a performance comparison with other popular implementations.
Python's ordinary dicts cannot be made to provide the keys/elements in any specific order. For that, you could use the OrderedDict type from the collections module. Note that the OrderedDict type merely keeps a record of insertion order. You would have to sort the entries prior to initializing the dictionary if you want subsequent views/iterators to return the elements in order every time. For example:
>>> myDic={10: 'b', 3:'a', 5:'c'}
>>> sorted_list=sorted(myDic.items(), key=lambda x: x[0])
>>> myOrdDic = OrderedDict(sorted_list)
>>> myOrdDic.items()
[(3, 'a'), (5, 'c'), (10, 'b')]
>>> myOrdDic[7] = 'd'
>>> myOrdDic.items()
[(3, 'a'), (5, 'c'), (10, 'b'), (7, 'd')]
If you want to maintain proper ordering for newly added items, you really need to use a different data structure, e.g., a binary tree/heap. This approach of building a sorted list and using it to initialize a new OrderedDict() instance is just woefully inefficient unless your data is completely static.
Edit: So, if the object of sorting the data is merely to print it in order, in a format resembling a python dict object, something like the following should suffice:
def pprint_dict(d):
strings = []
for k in sorted(d.iterkeys()):
strings.append("%d: '%s'" % (k, d[k]))
return '{' + ', '.join(strings) + '}'
Note that this function is not flexible w/r/t the types of the key, value pairs (i.e., it expects the keys to be integers and the corresponding values to be strings). If you need more flexibility, use something like strings.append("%s: %s" % (repr(k), repr(d[k]))) instead.
With Python 3.7 I could do this:
>>> myDic={10: 'b', 3:'a', 5:'c'}
>>> sortDic = sorted(myDic.items())
>>> print(dict(sortDic))
{3:'a', 5:'c', 10: 'b'}
If you want a list of tuples:
>>> myDic={10: 'b', 3:'a', 5:'c'}
>>> sortDic = sorted(myDic.items())
>>> print(sortDic)
[(3, 'a'), (5, 'c'), (10, 'b')]
Dictionaries are unordered by definition, What would be the main reason for ordering by key? A list of tuples created by the sort method can be used for whatever the need may have been, but changing the list of tuples back into a dictionary will return a random order
>>> myDic
{10: 'b', 3: 'a', 5: 'c'}
>>> sorted(myDic.items())
[(3, 'a'), (5, 'c'), (10, 'b')]
>>> print(dict(myDic.items()))
{10: 'b', 3: 'a', 5: 'c'}
Maybe not that good but I've figured this:
def order_dic(dic):
ordered_dic={}
key_ls=sorted(dic.keys())
for key in key_ls:
ordered_dic[key]=dic[key]
return ordered_dic
Any modern solution to this problem?
I worked around it with:
order = sorted([ job['priority'] for job in self.joblist ])
sorted_joblist = []
while order:
min_priority = min(order)
for job in self.joblist:
if job['priority'] == min_priority:
sorted_joblist += [ job ]
order.remove(min_priority)
self.joblist = sorted_joblist
The joblist is formatted as:
joblist = [ { 'priority' : 3, 'name' : 'foo', ... }, { 'priority' : 1, 'name' : 'bar', ... } ]
Basically I create a list (order) with all the elements by which I want to sort the dict
then I iterate this list and the dict, when I find the item on the dict I send it to a new dict and remove the item from 'order'.
Seems to be working, but I suppose there are better solutions.
I'm not sure whether this could help, but I had a similar problem and I managed to solve it, by defining an apposite function:
def sor_dic_key(diction):
lista = []
diction2 = {}
for x in diction:
lista.append([x, diction[x]])
lista.sort(key=lambda x: x[0])
for l in lista:
diction2[l[0]] = l[1]
return diction2
This function returns another dictionary with the same keys and relative values, but sorted by its keys.
Similarly, I defined a function that could sort a dictionary by its values. I just needed to use x[1] instead of x[0] in the lambda function. I find this second function mostly useless, but one never can tell!
I like python numpy for this kind of stuff! eg:
r=readData()
nsorted = np.lexsort((r.calls, r.slow_requests, r.very_slow_requests, r.stalled_requests))
I have an example of importing CSV data into a numpy and ordering by column priorities.
https://github.com/unixunion/toolbox/blob/master/python/csv-numpy.py
Kegan
The accepted answer definitely works, but somehow miss an important point.
The OP is asking for a dictionary sorted by it's keys this is just not really possible and not what OrderedDict is doing.
OrderedDict is maintaining the content of the dictionary in insertion order. First item inserted, second item inserted, etc.
>>> d = OrderedDict()
>>> d['foo'] = 1
>>> d['bar'] = 2
>>> d
OrderedDict([('foo', 1), ('bar', 2)])
>>> d = OrderedDict()
>>> d['bar'] = 2
>>> d['foo'] = 1
>>> d
OrderedDict([('bar', 2), ('foo', 1)])
Hencefore I won't really be able to sort the dictionary inplace, but merely to create a new dictionary where insertion order match key order. This is explicit in the accepted answer where the new dictionary is b.
This may be important if you are keeping access to dictionaries through containers. This is also important if you itend to change the dictionary later by adding or removing items: they won't be inserted in key order but at the end of dictionary.
>>> d = OrderedDict({'foo': 5, 'bar': 8})
>>> d
OrderedDict([('foo', 5), ('bar', 8)])
>>> d['alpha'] = 2
>>> d
OrderedDict([('foo', 5), ('bar', 8), ('alpha', 2)])
Now, what does mean having a dictionary sorted by it's keys ? That makes no difference when accessing elements by keys, this only matter when you are iterating over items. Making that a property of the dictionary itself seems like overkill. In many cases it's enough to sort keys() when iterating.
That means that it's equivalent to do:
>>> d = {'foo': 5, 'bar': 8}
>>> for k,v in d.iteritems(): print k, v
on an hypothetical sorted by key dictionary or:
>>> d = {'foo': 5, 'bar': 8}
>>> for k, v in iter((k, d[k]) for k in sorted(d.keys())): print k, v
Of course it is not hard to wrap that behavior in an object by overloading iterators and maintaining a sorted keys list. But it is likely overkill.
Sorting dictionaries by value using comprehensions. I think it's nice as 1 line and no need for functions or lambdas
a = {'b':'foo', 'c':'bar', 'e': 'baz'}
a = {f:a[f] for f in sorted(a, key=a.__getitem__)}
Easy and straightforward way:
op = {'1': (1,0,6),'3': (0,45,8),'2': (2,34,10)}
lp3 = sorted(op.items(), key=operator.itemgetter(0), reverse=True)
print(lp3)
ref: https://blog.csdn.net/weixin_37922873/article/details/81210032

Python: How to sort a dictionary of X and Y coordinates by ascending X coordinate value?

I have the following dictionary that I would like to sort based on their X coordinate in ascending fashion so that I can identify the "beacon" by the color arrangement (RGB in different orders). I keep trying to sort it like a list but that's not working out too well. Thanks in advance :)
Beacon2 = {
'r': [998.9282836914062, 367.3825378417969],
'b': [985.82373046875, 339.2225646972656],
'g': [969.539794921875, 369.2041931152344]
}
For this specific dictionary the expected result is
sortedBeacon = {
'g': [969.539794921875, 369.2041931152344],
'b': [985.82373046875, 339.2225646972656],
'r': [998.9282836914062, 367.3825378417969]
}
Note that dictionaries in general are not sortable. You can generate the internals sorted however without any lambdas by using itemgetter:
from operator import itemgetter
sorted_d = sorted(d.items(), key=itemgetter(1))
If you really want to maintain order, wrap the above in an OrderedDict
The method sort() in Python is normally used on lists and tuples whereas sorted() is better for data structures like dictionaries.
In this case, using a simple lambda function can help you get what you want.
print(sorted(Beacon2.values(), key = lambda x: (x[0]))
You can try this:
from collections import OrderedDict
Beacon2 = {'r': [998.9282836914062, 367.3825378417969], 'b':
[985.82373046875, 339.2225646972656], 'g': [969.539794921875, 369.2041931152344]}
sorted_beacons = sorted(Beacon2.items(), key = lambda x: x[1][0])
>>> print(OrderedDict(sorted_beacons))
OrderedDict([('g', [969.539794921875, 369.2041931152344]), ('b', [985.82373046875, 339.2225646972656]), ('r', [998.9282836914062, 367.3825378417969])])
Where you first sort the list of tuples from Beacon2.items(), with a sorting key applied on the X coordinate located at [1][0] of each tuple.
Note that you need to wrap an OrderedDict to your result to preserve order of the dictionary.
If you just want the values, use this:
sorted(data.values())
If you want the keys associated with the sorted values, use this:
sorted(data, key=data.get)
Both key and values:
sorted(data.items(), key=lambda x:x[1])
Courtesy of: sort dict by value python

Python remove a key from dictionary when It's a number [duplicate]

This question already has answers here:
Filter dict to contain only certain keys?
(22 answers)
Closed 6 years ago.
I'm trying to iterate over a dictionary in order to delete all items where the key is a number.
dict= {'hello':'3', 'baby':'5', '33':'6'}
for k in dict.keys():
if k.isdigit():
del dict[k]
The result i need is this:
dict={'hello':'3', 'baby':'5'}
I use the code above but it doesn't work?
Can somebody help me?
Instead of deleting items while looping through the dictionary, you can create a new dictionary:
dict_ = {'hello':'3', 'baby':'5', '33':'6'}
{k: v for k, v in dict_.items() if not k.isdigit()}
# {'baby': '5', 'hello': '3'}
The error RuntimeError: dictionary changed size during iteration, as it said, is raised because the dictionnary is modified during the iteration. One solution could be to first register all the keys, then modify the dictionnary:
dict= {'hello':'3', 'baby':'5', '33':'6'}
for k in tuple(dict.keys()): # iterate on a tuple of values that happened to be in dict's keys
if k.isdigit():
del dict[k]
The other, more pythonic, is to build the dictionnary in place, for instance using the dictionnary in intension notation like in this answer.
Btw, dict is a very bad name for an object of type dict.
The problem is because you are updating the dictionary while traversing. Rather first store the keys in a list and then remove from the dictionary.
Try this:
dic= {'hello':'3', 'baby':'5', '33':'6'}
x=dic.keys()
for k in x:
if k.isdigit():
del dic[k]
print dic
output :
{'baby': '5', 'hello': '3'}
Here is another solution using pop and map to modify in place your initial dictionary:
my_dict = {'a':1, 'b':2, 'c':3, '11':4, '12':5}
_ = map(lambda k: my_dict.pop(k), [k for k in my_dict if k.isdigit()])
# The map functions modifies in place your dictionary
Output :
>> my_dict
>> {'a': 1, 'b': 2, 'c': 3}

Python: Accessing individual values in a dictionary of a list of tuples [duplicate]

This question already has answers here:
Query Python dictionary to get value from tuple
(3 answers)
Closed 6 years ago.
I have a dictionary in Python where each key has a set of ten tuples. I am trying to iterate through the dictionary access the individual elements within each tuple- how should I go about that?
The dictionary looks like this:
{'Key1': [(Hi, 1), (Bye, 2)], 'Key2': [(Cats, Blue), (Dogs, Red)]}
Say I want vectors of the Keys, a vectors of the first elements [Hi, Bye, Cats, Dogs] and one of the second [1,2, Blue, red]
This is the code I was attempting:
for key in dict:
for tuplelist in dict:
key_vector.append(key_
tuple1_vector.append(dict[key[1]])
tuple2_vector.append(dict[key[2]])
I know this is incorrect but I am not sure how to go about fixing it.
I assume you mean your dict is:
your_dict = {'Key1': [('Hi', 1), ('Bye', 2)], 'Key2': [('Cats', 'Blue'), ('Dogs', 'Red')]}
You can iterate over all the keys, get whatever tuple is in there, and then iterate over all the entries inside that tuple. There probably is an easier way but this should at least get you there:
for key in your_dict:
for t in your_dict[key]:
for i in t:
print(i)
You can use .values() to access the values in the dictionary, then iterate over the values lists and index the respective items in the tuple:
tuple1_vector = []
tuple2_vector = []
for v in d.values():
for t in v:
tuple1_vector.append(t[0])
tuple2_vector.append(t[1])
You can also do this with a list comprehension:
tuple1_vector = [t[0] for v in d.values() for t in v]
tuple2_vector = [t[1] for v in d.values() for t in v]
print(tuple1_vector)
# ['Cats', 'Dogs', 'Hi', 'Bye']
print(tuple2_vector)
# ['Blue', 'Red', 1, 2]
You could do the following:
keys = []
tuple1 = []
tuple2 = []
for key in dict:
keys.append(key)
tuple1.append(dict[key][0][0])
tuple1.append(dict[key][0][1])
tuple1.append(dict[key][1][0])
tuple1.append(dict[key][1][1])
But do not, this is really bad code. I'm just showing a solution but that's not worth it. The other guys have made it better (such as iterating over dict[key] (e.g. for item in dict[key]...) .

index python dictionary by value [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Inverse dictionary lookup - Python
Is there a built in way to index a dictionary by value in Python.
e.g. something like:
dict = {'fruit':'apple','colour':'blue','meat':'beef'}
print key where dict[key] == 'apple'
or:
dict = {'fruit':['apple', 'banana'], 'colour':'blue'}
print key where 'apple' in dict[key]
or do I have to manually loop it?
You could use a list comprehension:
my_dict = {'fruit':'apple','colour':'blue','meat':'beef'}
print [key for key, value in my_dict.items() if value == 'apple']
The code above is doing almost exactly what said you want:
print key where dict[key] == 'apple'
The list comprehension is going through all the key, value pairs given by your dictionary's items method, and making a new list of all the keys where the value is 'apple'.
As Niklas pointed out, this does not work when your values could potentially be lists. You have to be careful about just using in in this case since 'apple' in 'pineapple' == True. So, sticking with a list comprehension approach requires some type checking. So, you could use a helper function like:
def equals_or_in(target, value):
"""Returns True if the target string equals the value string or,
is in the value (if the value is not a string).
"""
if isinstance(target, str):
return target == value
else:
return target in value
Then, the list comprehension below would work:
my_dict = {'fruit':['apple', 'banana'], 'colour':'blue'}
print [key for key, value in my_dict.items() if equals_or_in('apple', value)]
You'll have to manually loop it, but if you'll need the lookup repeatedly this is a handy trick:
d1 = {'fruit':'apple','colour':'blue','meat':'beef'}
d1_rev = dict((v, k) for k, v in d1.items())
You can then use the reverse dictionary like this:
>>> d1_rev['blue']
'colour'
>>> d1_rev['beef']
'meat'
Your requirements are more complex than you realize:
You need to handle both list values and plain values
You don't actually need to get back a key, but a list of keys
You could solve this in two steps:
normalize the dict so that every value is a list (every plain value becomes a single-element)
build a reverse dictionary
The following functions will solve this:
from collections import defaultdict
def normalize(d):
return { k:(v if isinstance(v, list) else [v]) for k,v in d.items() }
def build_reverse_dict(d):
res = defaultdict(list)
for k,values in normalize(d).items():
for x in values:
res[x].append(k)
return dict(res)
To be used like this:
>>> build_reverse_dict({'fruit':'apple','colour':'blue','meat':'beef'})
{'blue': ['colour'], 'apple': ['fruit'], 'beef': ['meat']}
>>> build_reverse_dict({'fruit':['apple', 'banana'], 'colour':'blue'})
{'blue': ['colour'], 'apple': ['fruit'], 'banana': ['fruit']}
>>> build_reverse_dict({'a':'duplicate', 'b':['duplicate']})
{'duplicate': ['a', 'b']}
So you just build up the reverse dictionary once and then lookup by value and get back a list of keys.

Categories

Resources