update method for dictionaries-Python - 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())))

Related

Dictionary with tuples key: All tuples with the same first element

I have dictionary in python whose keys are tuples, like:
my-dict={(1,'a'):value1, (1,'b'):value2, (1,'c'):value3, (2,'a'):value4,
(2,'b'):value5,(3,'a'):value6}
I need to access all values whose keys have the same first argument. For example, I need to access
{(1,'a'):value1, (1,'b'):value2, (1,'c'):value3}
because all of them have 1 as the first element of the tuple key. One way is to use a for and if:
for key in my-dict:
if key[0]==1:
do something
However, my actual dictionary and data are very huge and this method takes a lot of time. Is there any other way to efficiently do this?
You lose out on the benefits of creating a dictionary if you have to search through all its keys again. A good solution would be to create another dictionary That holds all keys which start with the correct first element.
my_dict={(1,'a'):'value1', (1,'b'):'value2', (1,'c'):'value3', (2,'a'):'value4',
(2,'b'):'value5',(3,'a'):'value6'}
from collections import defaultdict
mapping = defaultdict(list) #You do not need a defaultdict per se, i just find them more graceful when you do not have a certain key.
for k in my_dict:
mapping[k[0]].append(k)
Mapping now looks like this:
defaultdict(list,
{1: [(1, 'a'), (1, 'b'), (1, 'c')],
2: [(2, 'a'), (2, 'b')],
3: [(3, 'a')]})
Now Just use the dictionary to lookup the keys needed in your original dictionary.
first_element = 1
#Now just use the lookup to do some actions
for key in mapping[first_element]:
value = my_dict[key]
print(value)
#Do something
Output:
value1
value2
value3
The dict built-in type maps hashable values to arbitrary objects. In your dictionary, the tuples (1, 'a'), (1, 'b'), etc. all have different hashes.
You could try using Pandas multi-indexes to accomplish this. Here is a good example.
Alternatively, as one of the comments suggested, a nested dictionary may be more appropriate here. You can convert it from my_dict via
from collections import defaultdict
nested_dict = defaultdict(dict) # not necessary, but saves a line
for tup_key, value in my_dict.items():
key1, key2 = tup_key
nested_dict[key1][key2] = value
Then something like nested_dict[1] would give you
{'a':value1, 'b':value2, 'c':value3}

Sorting a dictionary by key in increasing order without using external libraries

I am trying to produce a dictionary that is the copy of another dictionary but with its keys sorted in increasing order. So far I have the following:
x = {89:1, 2:3, 3:1}
# produces x with its keys sorted in increasing order
# Example: sort(x) => {2:3, 3:1, 89:1}
def sort(x):
y = {}
for key in sorted(x):
y[key] = x[key]
print(y)
return y
Console output:
=>{2: 3}
=>{2: 3, 3: 1}
=>{89: 1, 2: 3, 3: 1}
=>{89: 1, 2: 3, 3: 1}
=>{89: 1, 2: 3, 3: 1} (the return statement)
The function seems to work fine for the first two keys (2 and 3) but then it breaks down when the last key is reached (89) and the function just spits out its input.
Why does the function work for the first two items but not for the last one? I don't think there is an aliasing problem here and I can't think of a clear reason for why this doesn't work.
I have researched this topic but none of the answers seem to reflect what I am looking for. I am planning to make this function work without the use of external libraries.
Any suggestions?
In python, dictionaries are not implemented with binary search trees. Actually if you check in the official documentation the explain:
It is best to think of a dictionary as an unordered set of key: value pairs, with the requirement that the keys are unique (within one dictionary).
Do not expect to see the elements on the dictionary sorted.
{key:a[key] for key in sorted(a.keys())} would be a more "Pythonic" way, BUT dictionaries have no order to them.
You could look at OrderedDict in collections.
from collections import OrderedDict
OrderedDict(sorted(x.items()))
Edited according to comments

sorting dates in key of tuples in dictionary

I have a dictionary with entries that are of the format
a = dict({(2,2013):[], (2,2011):[], (7,2013):[] , (4,2013):[]})
i want my output to be like this:
{(2,2011):[], (2,2013):[], (4,2013):[] , (7,2013):[]}
By the way its supposed to be (month,year), how can i achieve that?
import operator
myDict = {1: 1, 2: 2, 4:4, 2:1}
sorted_myDict = sorted(myDict.iteritems(), key=operator.itemgetter(1))
sorted_myDict will be a list of tuples sorted by the second element in each tuple.
#Decency answer is also very good option.
If you need to retain order for some reason, you can use an OrderedDict object.
Ordered dictionaries are just like regular dictionaries but they remember the order that items were inserted. When iterating over an ordered dictionary, the items are returned in the order their keys were first added.
Docs: http://docs.python.org/2/library/collections.html#collections.OrderedDict
class collections.OrderedDict([items])
after a lot of trying i changed my approach and instead of tuples, i used datetime objects and then applied the:
months_sorted = sorted(months.iteritems(), key=operator.itemgetter(0))

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