Dict with sorted keys - python

Is there a built-in dict subclass in the Python standard library that keeps the keys in their order, so that items() or keys() return in the order of keys (I mean not the order of insertion (which OrderedDict would do), but the actual relative order of the keys to each other). The equivalent for arrays would be a priority queue, but I haven't heard of anything like this for dicts.

Noticed that I missed the part of the question that says "keep it sorted". Some mentions from comments on the original question point to grantjenks.com/docs/sortedcontainers/sorteddict.html that looks good.
If there is no need to "keep sorted" the following helps.
This will do the trick:
sorted(my_dict.items())
For example:
for key, value in sorted(my_dict.items()):
print(key)
** update based on the comments **
If you want to return a dictionary with the sorted order (and guarantee it):
sorted_dict = OrderedDict(sorted(my_dict.items()))

By default, no dict keys are not sorted because of the properties of a dict object.
Try:
a = {'c': 'd', 'a': 'b', 'e': 'f'}
print(a.keys())
print(sorted(a.keys()))
And you can get the keys as a sorted list.

Related

Find the minimun element of a dictionary when min is eqal for all values python

I have this
my_dict = {'x':500, 'y':500, 'z': 500}
min_s=min(my_dict, key=my_dict.get)
when I print the min_s, it arbitrary print either x or y or z, but I want to just print the first key meaning x. How can I do this?
Also, how can I check if all values are the same ?
Thanks
Dictionaries in python are not (insertion) ordered, the order will basically follow whatever hash function the dictionary is using for your keys, and that can change everytime.
For (insertion) order preserving dictionaries you should use collections.OrderedDict, see the docs for more details: https://docs.python.org/2/library/collections.html#collections.OrderedDict
EDIT
However, for Python 3.6+ dicts will be insertion ordered. See this SO discussion for more details, or read the related PEP 468
Use OrderedDict to retain the insertion order:
from collections import OrderedDict
my_dict = OrderedDict(x=500, y=500, z=500)
min_s = min(my_dict) # 'x'
You can check that all values are the same by creating a set with the dict values and checking its length:
>>> len(set(my_dict.values())) == 1
True

The keys of a dictionary are not in the order when they are added?

>>> d={}
>>> d['c']=3
>>> d['b']=2
>>> d['a']=1
>>> d
{'a': 1, 'c': 3, 'b': 2}
>>> d.keys()
['a', 'c', 'b']
Are the keys in a dictionary not ordered in the same order they are added into the dictionary?
What order are they in?
What shall I do if I want to have the keys of a dictionary in the order that they are added into the dictionary?
Thanks.
dict is an unordered data structure. Keys will come out in some order when you iterate over them, but this may bear little resemblance to the order in which they were added. In return, you get O(1) lookup.
Use collections.OrderedDict if you need to retain the order.
Python dictionaries don't preserve order, and you cannot count on any particular order. Dictionary is a store for values where, by design, values are to be referred to by their keys – and not by a particular "slot" in which they are.
If you need to preserve order of added elements, use lists where a "slot" is referred to by an index, e.g. myList[3]. If you need to have 2 values coupled together (corresponding a "key" and a "value" as in your example), use a list of tuples.

update method for dictionaries-Python

I have written a code which tries to sort a dictionary using the values rather than keys
""" This module sorts a dictionary based on the values of the keys"""
adict={1:1,2:2,5:1,10:2,44:3,67:2} #adict is an input dictionary
items=adict.items()## converts the dictionary into a list of tuples
##print items
list_value_key=[ [d[1],d[0]] for d in items] """Interchanges the position of the
key and the values"""
list_value_key.sort()
print list_value_key
key_list=[ list_value_key[i][1] for i in range(0,len(list_value_key))]
print key_list ## list of keys sorted on the basis of values
sorted_adict={}
*for key in key_list:
sorted_adict.update({key:adict[key]})
print key,adict[key]
print sorted_adict*
So when I print key_list i get the expected answer, but for the last part of the code where i try to update the dictionary, the order is not what it should be. Below are the results obtained. I am not sure why the "update" method is not working. Any help or pointers is appreciated
result:
sorted_adict={1: 1, 2: 2, 67: 2, 5: 1, 10: 2, 44: 3}
Python dictionaries, no matter how you insert into them, are unordered. This is the nature of hash tables, in general.
Instead, perhaps you should keep a list of keys in the order their values or sorted, something like: [ 5, 1, 44, ...]
This way, you can access your dictionary in sorted order at a later time.
Don't sort like that.
import operator
adict={1:1,2:2,5:1,10:2,44:3,67:2}
sorted_adict = sorted(adict.iteritems(), key=operator.itemgetter(1))
If you need a dictionary that retains its order, there's a class called OrderedDict in the collections module. You can use the recipes on that page to sort a dictionary and create a new OrderedDict that retains the sort order. The OrderedDict class is available in Python 2.7 or 3.1.
To sort your dictionnary, you could also also use :
adict={1:1,2:2,5:1,10:2,44:3,67:2}
k = adict.keys()
k.sort(cmp=lambda k1,k2: cmp(adict[k1],adict[k2]))
And by the way, it's useless to reuse a dictionnary after that because there are no order in dict (they are just mapping types - you can have keys of different types that are not "comparable").
One problem is that ordinary dictionaries can't be sorted because of the way they're implemented internally. Python 2.7 and 3.1 had a new class namedOrderedDictadded to theircollectionsmodule as #kindall mentioned in his answer. While they can't be sorted exactly either, they do retain or remember the order in which keys and associated values were added to them, regardless of how it was done (including via theupdate() method). This means that you can achieve what you want by adding everything from the input dictionary to anOrderedDictoutput dictionary in the desired order.
To do that, the code you had was on the right track in the sense of creating what you called thelist_value_keylist and sorting it. There's a slightly simpler and faster way to create the initial unsorted version of that list than what you were doing by using the built-inzip()function. Below is code illustrating how to do that:
from collections import OrderedDict
adict = {1:1, 2:2, 5:1, 10:2, 44:3, 67:2} # input dictionary
# zip together and sort pairs by first item (value)
value_keys_list = sorted(zip(adict.values(), adict.keys()))
sorted_adict = OrderedDict() # value sorted output dictionary
for pair in value_keys_list:
sorted_adict[pair[1]] = pair[0]
print sorted_adict
# OrderedDict([(1, 1), (5, 1), (2, 2), (10, 2), (67, 2), (44, 3)])
The above can be rewritten as a fairly elegant one-liner:
sorted_adict = OrderedDict((pair[1], pair[0])
for pair in sorted(zip(adict.values(), adict.keys())))

How to print unsorted dictionary in python?

I have this dict in python;
d={}
d['b']='beta'
d['g']='gamma'
d['a']='alpha'
when i print the dict;
for k,v in d.items():
print k
i get this;
a
b
g
it seems like python sorts the dict automatically! how can i get the original unsorted list?
Gath
Dicts don't work like that:
CPython implementation detail: Keys and values are listed in an arbitrary order which is non-random, varies across Python implementations, and depends on the dictionary’s history of insertions and deletions.
You could use a list with 2-tuples instead:
d = [('b', 'beta'), ('g', 'gamma'), ('a', 'alpha')]
A similar but better solution is outlined in Wayne's answer.
As has been mentioned, dicts don't order or unorder the items you put in. It's "magic" as to how it's ordered when you retrieve it. If you want to keep an order -sorted or not- you need to also bind a list or tuple.
This will give you the same dict result with a list that retains order:
greek = ['beta', 'gamma', 'alpha']
d = {}
for x in greek:
d[x[0]] = x
Simply change [] to () if you have no need to change the original list/order.
Don't use a dictionary. Or use the Python 2.7/3.1 OrderedDict type.
There is no order in dictionaries to speak of, there is no original unsorted list.
No, python does not sort dict, it would be too expensive. The order of items() is arbitrary. From python docs:
CPython implementation detail: Keys
and values are listed in an arbitrary
order which is non-random, varies
across Python implementations, and
depends on the dictionary’s history of
insertions and deletions.

python: arbitrary order by

In Oracle SQL there is a feature to order as follow:
order by decode("carrot" = 2
,"banana" = 1
,"apple" = 3)
What is the best way to implement this in python?
I want to be able to order a dict by its keys. And that order isn't necessarily alphabetically or anything - I determine the order.
Use the key named keyword argument of sorted().
#set up the order you want the keys to appear here
order = ["banana", "carrot", "apple"]
# this uses the order list to sort the actual keys.
sorted(keys, key=order.index)
For higher performance than list.index, you could use dict.get instead.
#this builds a dictionary to lookup the desired ordering
order = dict((key, idx) for idx, key in enumerate(["banana", "carrot", "apple"]))
# this uses the order dict to sort the actual keys.
sorted(keys, key=order.get)
You can't order a dict per se, but you can convert it to a list of (key, value) tuples, and you can sort that.
You use the .items() method to do that. For example,
>>> {'a': 1, 'b': 2}
{'a': 1, 'b': 2}
>>> {'a': 1, 'b': 2}.items()
[('a', 1), ('b', 2)]
Most efficient way to sort that is to use a key function. using cmp is less efficient because it has to be called for every pair of items, where using key it only needs to be called once for every item. Just specify a callable that will transform the item according to how it should be sorted:
sorted(somedict.items(), key=lambda x: {'carrot': 2, 'banana': 1, 'apple':3}[x[0]])
The above defines a dict that specifies the custom order of the keys that you want, and the lambda returns that value for each key in the old dict.
Python's dict is a hashmap, so it has no order. But you can sort the keys separately, extracting them from the dictionary with keys() method.
sorted() takes comparison and key functions as arguments.
You can do exact copy of your decode with
sortedKeys = sorted(dictionary, {"carrot": 2
,"banana": 1
,"apple": 3}.get);
You can't sort a dictionary; a dictionary is a mapping and a mapping has no ordering.
You could extract the keys and sort those, however:
keys = myDict.keys()
sorted_keys = sorted(keys, myCompare)
There will be OrderedDict in new Python versions: http://www.python.org/dev/peps/pep-0372/.
Meanwhile, you can try one of the alternative implementations: http://code.activestate.com/recipes/496761/, Ordered Dictionary.
A dict is not ordered. You will need to keep a list of keys.
You can pass your own comparison function to list.sort() or sorted().
If you need to sort on multiple keys, just concatenate them in a tuple, and sort on the tuple.

Categories