Related
how to merge two dictionaries in python 2.7 without changing the order of keys in it. as I have to make a CSV file in the required order. I just want to add B dictionary after A dictionary values.
def Merge(A,B):
m=A.copy()
m.update(B)
return m
I am using this method. I also try with +. but the same result. ** is not working in python 2.7
Dictionaries are unordered containers. So, what you say is not correct. That is, if you simply have two dictionaries, then you have no order.
BUT! You have can order the keys of a dictionary, using the OrderedDict container.
You can consider something like:
>>> from collections import OrderedDict
>>> a = OrderedDict({'a': 1, 'b': 2})
>>> b = OrderedDict({'c': 3, 'd': 4})
>>> c = OrderedDict()
>>>for d in [a, b]:
... for k, v in d.items():
... c.update({k :v})
>>> print(c)
OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 4)])
# Or
>>> d = OrderedDict()
>>> d.update(a.copy())
>>> d.update(b.copy())
>>> print(d)
OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 4)])
Or, if you want a function:
from collections import OrderedDict
def merge(a, b):
c = OrderedDict()
c.update(a.copy())
c.update(b.copy())
return c
You can read more about OrderedDict here.
Dictionaries are unordered in Python 2. If you need to preserve the order of keys, you'll have to use something else, like a list of pairs, or an OrderedDict. Here's one approach.
from collections import OrderedDict
def merge(a, b):
return OrderedDict((k, v) for d in [a, b] for k, v in d.items())
Dictionaries is considered as an unordered collection of values mapped to certain keys. First, make an ordered dictionary by using OrderedDict from the collections library. Then using the method update() you can create the new dictionary. Here's an example.
# A Python program to demonstrate working of OrderedDict
from collections import OrderedDict
#Form OrderedDicts
dict1 = OrderedDict({"a": 1, "b": 2})
dict2 = OrderedDict({"c": 3, "d": 4})
print "These are two ordered dictionaries:\n"
print dict1 , dict2
#Using update method in python
def Merge(dict1, dict2):
return(dict1.update(dict2))
#Make a duplicate of the first dictionary
dict3 = dict1
#Call function
Merge(dict3, dict2)
print "Combined dictionary:", dict3
If you are just going to make a csv you can create a list of items from both ensuring that the items from one are after the items of the other. Then use the list of tuples to make the csv.
a = {1:1,2:2}
b = {3:3,4:4}
combined = []
combined.extend(a.items())
combined.extend(b.items())
In [8]: combined
Out[8]: [(1, 1), (2, 2), (3, 3), (4, 4)]
This is the following problem:
main_module.py
from collections import OrderedDict
from my_other_module import foo
a = OrderedDict([
('a', 1),
('b', 2),
('c', 3),
('d', 4),
])
foo(**a)
my_other_module.py
def foo(**kwargs):
for k, v in kwargs.items():
print k, v
When i run main_module.py I'm expecting to get printout with the order I specified:
a 1
b 2
c 3
d 4
But instead I'm getting:
a 1
c 3
b 2
d 4
I do understand that this has something to do with the way ** operator is implemented and somehow it looses order how dictionary pairs are passed in. Also I do understand that dictionaries in python are not ordered as lists are, because they're implemented as hash tables. Is there any kind of 'hack' that I could apply so I get the behaviour that is needed in this context?
P.S. - In my situation I can't sort the dictionary inside foo function since there are no rules which could be followed except strict order that values are passed in.
By using **a you're unpacking the ordered dictionary into an argument dictionary.
So when you enter in foo, kwargs is just a plain dictionary, with order not guaranteed (unless you're using Python 3.6+, but that's still an implementation detail in 3.6 - the ordering becomes official in 3.7: Are dictionaries ordered in Python 3.6+?)
You could just lose the packing/unpacking in that case so it's portable for older versions of python.
from collections import OrderedDict
def foo(kwargs):
for k, v in kwargs.items():
print(k, v)
a = OrderedDict([
('a', 1),
('b', 2),
('c', 3),
('d', 4),
])
foo(a)
I am trying to get a sorted dictionary. But the order of the items between mydict and orddict doesn't seem to change.
from collections import OrderedDict
mydict = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
orddict = OrderedDict(mydict)
print(mydict, orddict)
# print items in mydict:
print('mydict')
for k, v in mydict.items():
print(k, v)
print('ordereddict')
# print items in ordered dictionary
for k, v in orddict.items():
print(k, v)
# print the dictionary keys
# for key in mydict.keys():
# print(key)
# print the dictionary values
# for value in mydict.values():
# print(value)
As of Python 3.7, a new improvement to the dict built-in is:
the insertion-order preservation nature of dict objects has been declared to be an official part of the Python language spec.
This means there is no real need for OrderedDict anymore 🎉. They are almost the same.
Some minor details to consider...
Here are some comparisons between Python 3.7+ dict and OrderedDict:
from collections import OrderedDict
d = {'b': 1, 'a': 2}
od = OrderedDict([('b', 1), ('a', 2)])
# they are equal with content and order
assert d == od
assert list(d.items()) == list(od.items())
assert repr(dict(od)) == repr(d)
Obviously, there is a difference between the string representation of the two object, with the dict object in more natural and compact form.
str(d) # {'b': 1, 'a': 2}
str(od) # OrderedDict([('b', 1), ('a', 2)])
As for different methods between the two, this question can be answered with set theory:
d_set = set(dir(d))
od_set = set(dir(od))
od_set.difference(d_set)
# {'__dict__', '__reversed__', 'move_to_end'} for Python 3.7
# {'__dict__', 'move_to_end'} for Python 3.8+
This means OrderedDict has at most two features that dict does not have built-in, but work-arounds are shown here:
Workaround for __reversed__ / reversed()
No workaround is really needed for Python 3.8+, which fixed this issue. OrderedDict can be "reversed", which simply reverses the keys (not the whole dictionary):
reversed(od) # <odict_iterator at 0x7fc03f119888>
list(reversed(od)) # ['a', 'b']
# with Python 3.7:
reversed(d) # TypeError: 'dict' object is not reversible
list(reversed(list(d.keys()))) # ['a', 'b']
# with Python 3.8+:
reversed(d) # <dict_reversekeyiterator at 0x16caf9d2a90>
list(reversed(d)) # ['a', 'b']
To properly reverse a whole dictionary using Python 3.7+:
dict(reversed(list(d.items()))) # {'a': 2, 'b': 1}
Workaround for move_to_end
OrderedDict has a move_to_end method, which is simple to implement:
od.move_to_end('b') # now it is: OrderedDict([('a', 2), ('b', 1)])
d['b'] = d.pop('b') # now it is: {'a': 2, 'b': 1}
An OrderedDict preserves the order elements were inserted:
>>> od = OrderedDict()
>>> od['c'] = 1
>>> od['b'] = 2
>>> od['a'] = 3
>>> od.items()
[('c', 1), ('b', 2), ('a', 3)]
>>> d = {}
>>> d['c'] = 1
>>> d['b'] = 2
>>> d['a'] = 3
>>> d.items()
[('a', 3), ('c', 1), ('b', 2)]
So an OrderedDict does not order the elements for you, it preserves the order you give it.
If you want to "sort" a dictionary, you probably want
>>> sorted(d.items())
[('a', 1), ('b', 2), ('c', 3)]
Starting with CPython 3.6 and all other Python implementations starting with Python 3.7, the built-in dict is ordered - you get the items out in the order you inserted them. Which makes dict and OrderedDict effectively the same.
The documentation for OrderedDict lists the remaining differences. The most important one is that
The equality operation for OrderedDict checks for matching order.
Then there's a few minor practical differences:
dict.popitem() takes no arguments, whereas OrderedDict.popitem(last=True) accepts an optional last= argument that lets you pop the first item instead of the last item.
OrderedDict has a move_to_end(key, last=True) method to efficiently reposition an element to the end or the beginning. With dicts you can move a key to the end by re-inserting it: mydict['key'] = mydict.pop('key')
Until Python 3.8, you could do reversed(OrderedDict()) but reversed({}) would raise a TypeError: 'dict' object is not reversible error because they forgot to add a __reversed__ dunder method to dict when they made it ordered. This is now fixed.
And there are a few under-the-hood differences that might mean that you could get better performance for some specific usecase with OrderedDict:
The regular dict was designed to be very good at mapping
operations. Tracking insertion order was secondary.
The OrderedDict was designed to be good at reordering operations.
Space efficiency, iteration speed, and the performance of update
operations were secondary.
Algorithmically, OrderedDict can handle frequent reordering
operations better than dict. This makes it suitable for tracking
recent accesses (for example in an LRU cache).
See this great talk from 2016 by Raymond Hettinger for details on how Python dictionaries are implemented.
Adding on to the answer by Brian, OrderedDict is really great. Here's why:
You can use it as simple dict object because it supports equality testing with other Mapping objects like collections.counter.
OrderedDict preserves the insertion order as explained by Brian. In addition to that it has a method popitem which returns (key,value) pairs in LIFO order. So, you can also use it as a mapped 'stack'.
You not only get the full features of a dict but also, some cool tricks.
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.
So it only sorts by order of adding into the dict
You can build an OrderedDict order by key as follow,
orddict = OrderedDict(sorted(mydict.items(), key = lambda t: t[0]))
or simply as #ShadowRanger mentioned in comment
orddict = OrderedDict(sorted(d.items()))
If you want to order by value,
orddict = OrderedDict(sorted(mydict.items(), key = lambda t: t[1]))
More information in 8.3.5.1. OrderedDict Examples and Recipes
Besides the answers from ~3 years ago in this question:
Can I do an ordered, default dict in Python?
Have any implementations been adopted into recent versions of Python?
If not, why not?
No, for default options, you will only have the built-in dictionary which is not ordered. If you do want an ordered dictionary, you will have to import the module OrderedDict.
from collections import OrderedDict
>>> od = OrderedDict([('a', 1), ('b', 2), ('c', 3)])
You do, however, have the option of creating a list of tuples which will maintain its order.
Instead of:
a = {'a': 1, 'b': 2, 'c':3}
you would do it as:
a = [('a', 1), ('b', 2), ('c', 3)]
I'm afraid I'm not on 2.7, so cannot test, but this should reimplement a defaultdict subclassed from OrderedDict:
from collections import OrderedDict
class DefaultOrderedDict(OrderedDict):
def __init__(self, default):
self.default = default
def __getitem__(self, x):
try:
return OrderedDict.__getitem__(self, x)
except KeyError:
self[x] = self.default()
return self[x]
I want to loop through multiple dictionaries to find a value residing in it. If the value is found, I want values and THE NAME of the dict returned. I have written a function to do it but I cannot extract the name only the complete dict. Here is the code:
a = {1: ((1,1),999), 2: ((2,2),998), 3:((3,3),998)}
b = {1: ((4,4),997), 5:((5,5),996)}
def retOBJECT(tup):
for l in [a,b]:
for v in l:
if tup in l[v]:
return l,v,l[v][1]
print retOBJECT((1,1))
>>>
({1: ((1, 1), 999), 2: ((2, 2), 998), 3: ((3, 3), 998)}, 1, 999)
I do not want the whole dictionary returned but only its name so I know where the other values come from, i.e. the last two numbers.
And this is how I want it to look like:
>>> ('a', 1, 999)
Can anyone help here. I have always found excellent advice here and I am looking forward to some genius pointing out how to retrieve the name of a dictionary.
def retOBJECT(tup):
for l_name, l in [('a',a),('b',b)]:
for v in l:
if tup in l[v]:
return l_name, v,l[v][1]
a and b are just references to the dictionary objects, So whenever you use a and b python actually uses the objects they are pointing to.
Though you can use globals() to achieve what you were trying to do, but I don't know why would you wanna do that:
globals() -> dictionary
Return the dictionary containing the current scope's global variables.
In [110]: globals()['a']
Out[110]: {1: ((1, 1), 999), 2: ((2, 2), 998), 3: ((3, 3), 998)}
In [111]: def retOBJECT(tup):
for l in ['a','b']:
for v in globals()[l]:
if tup in globals()[l][v]:
return l,v,globals()[l][v][1]
.....:
In [112]: print retOBJECT((1,1))
('a', 1, 999)
In [113]: print retOBJECT((2,2))
('a', 2, 998)
In [114]: print retOBJECT((5,5))
('b', 5, 996)
If you really want the name of the dict, I would suggest giving the dictionary a 'name' key, which holds the 'name' of the dict.
a['name'] = 'a'
You could also make a a tuple with the 'name' of the object, and the dict.
a = ('a', some_dict)
I think the recommended way would be wrapping your entire data structure in a dict, something like:
names = {}
names["a"] = {1: ((1,1),999), 2: ((2,2),998), 3:((3,3),998)}
names["b"] = {1: ((4,4),997), 5:((5,5),996)}
def ret_name(tup):
for k1, v1 in names.iteritems():
for k2, v2 in names[k1].iteritems():
if v2[0]==tup:
return names[k1], k1, names[k1][k2][1]
print ret_name( (1,1) )
print ret_name( (5,5) )
Use your dicts as keyword arguments to the function:
a = {1: ((1,1),999), 2: ((2,2),998), 3:((3,3),998)}
b = {1: ((4,4),997), 5:((5,5),996)}
def ret_obj(tpl,**kwargs):
for k,v in kwargs.iteritems():
for k2,v2 in v.iteritems():
if tpl in v2:
return (k,k2,v2[1])
ret_obj((1,1),a=a,b=b)
#returns ('a', 1, 999)
Thank you so much guys. There are a few really valuable results, but I explicitly like ilmiacs, volatility and root's approach, since they are straightforward and easy to implement. I am glad that you helped me solve this problem and I can tackle my project. Cheers !!