Set of Dictionary elements - python

I want to create a set of dictionaries in python. I know how to make a list of dictionaries and convert it to set, but I want to add a dictionary to a set. Can anyone help me?
I got this error when I try below code:
"Exception has occurred: TypeError unhashable type: 'dict'"
C = set()
A = {'a':1, 'c':2, 'd':3}
B = {'c':3, 'd':4, 2:5 }
C.add(A)
C.add(B)
Thanks

For the below:
C = set()
A = {'a':1, 'c':2, 'd':3}
B = {'c':3, 'd':4, 2:5 }
You could do something like this to combine all the above into a single set. I will use an union operator '|' to achieve this.
{i for i in A.items()} | {i for i in B.items()}
This results to:
{('a', 1), ('c', 2), ('c', 3), ('d', 3), ('d', 4), (2, 5)}
** Extra Information **
If you knew from the start that dictionary B does not contain any of the keys found in dictionary A, you could do something like the below to combine the two dictionaries:
For example:
A = {'a':1, 'c':2, 'd':3}
B = {'e':3, 'f':4, 2:5 }
from collections import Counter
C = Counter(A) + Counter(B)
C equates to the below:
Counter({'a': 1, 'c': 2, 'd': 3, 'e': 3, 'f': 4, 2: 5})

Related

Sort by sum of values in a list for dictionary python

I have a dictionary like this:
d = {'a':[{'a1':1},{'a2':5},{'a3':4}], 'b':[{'b1':0},{'b2':1},{'b3':2}], 'c':[{'c1':1},{'c2':2}]}
I'd like to sort it by the sum of values in each list (values of each item in the dictionary) so that it will result in:
r = [('a', (10, [{'a1':1},{'a2':5},{'a3':4}])),
('b', (3, [{'b1':0},{'b2':1},{'b3':2}])),# 'b' and 'c' have sum of '3', so they tied here
('c', (3, [{'c1':1},{'c2':2}]))]
I can get this done in a naive approach. I'd like to know how to accomplish this in more Pythonic way. I have tried this, but didn't work for obvious reason:
sorted(sum(d.values()), key=d.get, reverse=True)
Thank you in advance for your answers!
You can try this:
d = {'a':[{'a1':1},{'a2':5},{'a3':4}], 'b':[{'b1':0},{'b2':1},{'b3':2}], 'c':[{'c1':1},{'c2':2}]}
new_d = {a:(sum(list(i.values())[0] for i in b), b) for a, b in d.items()}
final_result = sorted(new_d.items(), key=lambda x:x[-1][0], reverse=True)
Output:
('a', (10, [{'a1': 1}, {'a2': 5}, {'a3': 4}])), ('c', (3, [{'c1': 1}, {'c2': 2}])), ('b', (3, [{'b1': 0}, {'b2': 1}, {'b3': 2}]))]

How to merge 2 ordered dictionaries in python?

I have 2 ordered dictionaries, like:
a = collections.OrderedDict()
b = collections.OrderedDict()
And they have stuff in them. How do I merge these 2? I tried:
mergeDict = dict(a.items() + b.items())
but doing this it's not a ordered dictionary anymore.
What I am looking for: if a = {1, 2, 5, 6} and b = [0, 7, 3, 9} then mergeDict = {1, 2, 5, 6, 0, 7, 3, 9}
Two ways (assuming Python 3.6):
Use "update method". Suppose there are two dictionaries:
>>> d1 = collections.OrderedDict([('a', 1), ('b', 2)])
>>> d2 = {'c': 3, 'd': 4}
>>> d1.update(d2)
>>> d1
OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 4)])
Second method using 'concatenation operator (+)'
>>> d1 = collections.OrderedDict([('a', 1), ('b', 2)])
>>> d2 = {'c': 3, 'd': 4}
>>> d3 = collections.OrderedDict(list(d1.items()) + list(d2.items()))
>>> d3
OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 4)])
from itertools import chain
from collections import OrderedDict
OrderedDict(chain(a.items(), b.items()))
CPython 3.6, and any 3.7+ interpreter already preserves dictionary key ordering.
This allows you to do use the {**a, **b} syntax.
For example:
>>> a = {1: "AA", 2: "BB", 5: "CC", 6: "DD"}
>>> b = {0: "EE", 7: "FF", 3: "GG", 9: "HH"}
>>> {**a, **b}
{1: 'AA', 2: 'BB', 5: 'CC', 6: 'DD', 0: 'EE', 7: 'FF', 3: 'GG', 9: 'HH'}
instead of dict use back OrderedDict for mergeDict
mergeDict = collections.OrderedDict(a.items() + b.items())
Remark :this only works for python 2.x, add list() over dict.items() for python 3 because dict.items() no longer return list that support + operation
or use a.update(b) like #alfasin mentions in comment
i try with simple example and both method works well for me

How to sort keys of dict by values?

I have a dict {'a': 2, 'b': 0, 'c': 1}.
Need to sort keys by values so that I can get a list ['b', 'c', 'a']
Is there any easy way to do this?
sorted_keys = sorted(my_dict, key=my_dict.get)
>>> d={'a': 2, 'b': 0, 'c': 1}
>>> [i[0] for i in sorted(d.items(), key=lambda x:x[1])]
['b', 'c', 'a']
try this:
import operator
lst1 = sorted(lst.items(), key=operator.itemgetter(1))
There's a simple way to do it.
You can use .items() to get key-value and use sorted to sort them accordingly.
dictionary = sorted(dictionary.items(),key=lambda x:x[1])
>>> d = {'a':2, 'b':0, 'c':1}
>>> sor = sorted(d.items(), key=lambda x: x[1])
>>> sor
[('b', 0), ('c', 1), ('a', 2)]
>>> for i in sor:
... print i[0]
...
b
c
a

Updating a dictionary in python

I've been stuck on this question for quite sometime and just can't figure it out. I just want to be able to understand what I'm missing and why it's needed.
What I need to do is make a function which adds each given key/value pair to the dictionary. The argument key_value_pairs will be a list of tuples in the form (key, value).
def add_to_dict(d, key_value_pairs):
newinputs = [] #creates new list
for key, value in key_value_pairs:
d[key] = value #updates element of key with value
if key in key_value_pairs:
newinputs.append((d[key], value)) #adds d[key and value to list
return newinputs
I can't figure out how to update the "value" variable when d and key_value_pairs have different keys.
The first three of these scenarios work but the rest fail
>>> d = {}
>>> add_to_dict(d, [])
[]
>>> d
{}
>>> d = {}
>>> add_to_dict(d, [('a', 2])
[]
>>> d
{'a': 2}
>>> d = {'b': 4}
>>> add_to_dict(d, [('a', 2)])
[]
>>> d
{'a':2, 'b':4}
>>> d = {'a': 0}
>>> add_to_dict(d, [('a', 2)])
[('a', 0)]
>>> d
{'a':2}
>>> d = {'a', 0, 'b': 1}
>>> add_to_dict(d, [('a', 2), ('b': 4)])
[('a', 2), ('b': 1)]
>>> d
{'a': 2, 'b': 4}
>>> d = {'a': 0}
>>> add_to_dict(d, [('a', 1), ('a': 2)])
[('a', 0), ('a':1)]
>>> d
{'a': 2}
Thanks
Edited.
Python has this feature built-in:
>>> d = {'b': 4}
>>> d.update({'a': 2})
>>> d
{'a': 2, 'b': 4}
Or given you're not allowed to use dict.update:
>>> d = dict(d.items() + {'a': 2}.items()) # doesn't work in python 3
With python 3.9 you can use an |= update operator:
>>> d = {'b': 4}
>>> d |= {'a': 2}
>>> d
{'a': 2, 'b': 4}
Here's a more elegant solution, compared to Eric's 2nd snippet
>>> a = {'a' : 1, 'b' : 2}
>>> b = {'a' : 2, 'c' : 3}
>>> c = dict(a, **b)
>>> a
{'a': 1, 'b': 2}
>>> b
{'a': 2, 'c': 3}
>>> c
{'a': 2, 'b': 2, 'c': 3}
It works both in Python 2 and 3
And of course, the update method
>>> a
{'a': 1, 'b': 2}
>>> b
{'a': 2, 'c': 3}
>>> a.update(b)
>>> a
{'a': 2, 'b': 2, 'c': 3}
However, be careful with the latter, as might cause you issues in case of misuse like here
>>> a = {'a' : 1, 'b' : 2}
>>> b = {'a' : 2, 'c' : 3}
>>> c = a
>>> c.update(b)
>>> a
{'a': 2, 'b': 2, 'c': 3}
>>> b
{'a': 2, 'c': 3}
>>> c
{'a': 2, 'b': 2, 'c': 3}
The new version of Python3.9 introduces two new operators for dictionaries: union (|) and in-place union (|=). You can use | to merge two dictionaries, while |= will update a dictionary in place. Let's consider 2 dictionaries d1 and d2
d1 = {"name": "Arun", "height": 170}
d2 = {"age": 21, "height": 170}
d3 = d1 | d2 # d3 is the union of d1 and d2
print(d3)
Output:
{'name': 'Arun', 'height': 170, 'age': 21}
Update d1 with d2
d1 |= d2
print(d1)
Output:
{'name': 'Arun', 'height': 170, 'age': 21}
You can update d1 with a new key weight as
d1 |= {"weight": 80}
print(d1)
Output:
{'name': 'Arun', 'height': 170, 'age': 21, 'weight': 80}
So if I understand you correctly you want to return a list of of tuples with (key, old_value) for the keys that were replaced.
You have to save the old value before you replace it:
def add_to_dict(d, key_value_pairs):
newinputs = [] #creates new list
for key, value in key_value_pairs:
if key in d:
newinputs.append((key, d[key]))
d[key] = value #updates element of key with value
return newinputs
Each key in a python dict corresponds to exactly one value. The cases where d and key_value_pairs have different keys are not the same elements.
Is newinputs supposed to contain the key/value pairs that were previously not present in d? If so:
def add_to_dict(d, key_value_pairs):
newinputs = []
for key, value in key_value_pairs:
if key not in d:
newinputs.append((key, value))
d[key] = value
return newinputs
Is newinputs supposed to contain the key/value pairs where the key was present in d and then changed? If so:
def add_to_dict(d, key_value_pairs):
newinputs = []
for key, value in key_value_pairs:
if key in d:
newinputs.append((key, value))
d[key] = value
return newinputs
If I understand you correctly, you only want to add the keys that do not exist in the dictionary. Here is the code:
def add_to_dict(d, key_value_pairs):
newinputs = [];
for key, value in key_value_pairs:
if key not in d.keys():
d[key] = value
newinputs.append((key, value));
return newinputs
For each key in new key,value pairs list you have to check if the key is new to the dictionary and add it only then.
Hope it helps ;)

create dictionary from list - in sequence

I would like to create a dictionary from list
>>> list=['a',1,'b',2,'c',3,'d',4]
>>> print list
['a', 1, 'b', 2, 'c', 3, 'd', 4]
I use dict() to produce dictionary from list
but the result is not in sequence as expected.
>>> d = dict(list[i:i+2] for i in range(0, len(list),2))
>>> print d
{'a': 1, 'c': 3, 'b': 2, 'd': 4}
I expect the result to be in sequence as the list.
{'a': 1, 'b': 2, 'c': 3, 'd': 4}
Can you guys please help advise?
Dictionaries don't have any order, use collections.OrderedDict if you want the order to be preserved. And instead of using indices use an iterator.
>>> from collections import OrderedDict
>>> lis = ['a', 1, 'b', 2, 'c', 3, 'd', 4]
>>> it = iter(lis)
>>> OrderedDict((k, next(it)) for k in it)
OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 4)])
Dictionary is an unordered data structure. To preserve order use collection.OrderedDict:
>>> lst = ['a',1,'b',2,'c',3,'d',4]
>>> from collections import OrderedDict
>>> OrderedDict(lst[i:i+2] for i in range(0, len(lst),2))
OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 4)])
You could use the grouper recipe: zip(*[iterable]*n) to collect the items into groups of n:
In [5]: items = ['a',1,'b',2,'c',3,'d',4]
In [6]: items = iter(items)
In [7]: dict(zip(*[items]*2))
Out[7]: {'a': 1, 'b': 2, 'c': 3, 'd': 4}
PS. Never name a variable list, since it shadows the builtin (type) of the same name.
The grouper recipe is easy to use, but a little harder to explain.
Items in a dict are unordered. So if you want the dict items in a certain order, use a collections.OrderedDict (as falsetru already pointed out):
In [13]: collections.OrderedDict(zip(*[items]*2))
Out[13]: OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 4)])

Categories

Resources