Merge a dictionary and a list - python

Am trying to combine a dictionary and a list which has dictionaries and an empty dictionary
dict1 = {'a': 1, 'b': 2}
list1 = [{'c': 3}, {'d':4}]
emptydict = {}
emptylist = []
Trying to merge and make it a final dictionary which looks like below.
final = {'a': 1, 'b': 2, 'c': 3, 'd':4}
Code:
final = {**dict1, **list1[0], **list1[1], **emptydict, **emptylist}
Here I dont know the length of list1, can anyone suggest me a better way than this ?

dict.update updates an existing dictionary. Unfortunately it’s a mutating method that does not return a value. Therefore adapting it to functools.reduce requires a wrapper.
Due to this, I’d be tempted to use a good old loop:
final = dict(dict1)
for d in list1:
final.update(d)
But for completeness, here’s a way using functools.reduce:
import functools
def dict_update(d, v):
d.update(v)
return d
final = functools.reduce(dict_update, list1, dict1.copy())

If you are using python 3.3+, you can use ChainMap to merge list of dicts into a single dict. And then use ** operator to merge dict1 and dict(ChainMap(*list1)).
from collections import ChainMap
final = {**dict1, **ChainMap(*list1)}

Related

Converting dictionary into string

d={'a':'Apple','b':'ball','c':'cat'}
The above dictionary I have and I want my Output like the below-mentioned result
res="a=Apple,b=ball,c=cat"
Is it possible in a pythonic way then please answer it I have tried various method but did not get desired output?
Read your dictionary as key/value pairs (dict.items()) and then just format them in a string you like:
d = {'a': 'Apple', 'b': 'ball', 'c': 'cat'}
res = ",".join("{}={}".format(*i) for i in d.items()) # a=Apple,c=cat,b=ball
The order, tho, cannot be guaranteed for a dict, use collections.OrderedDict() if order is important.
One way is to iterate via dict.items and use multiple str.join calls.
d = {'a':'Apple','b':'ball','c':'cat'}
res = ','.join(['='.join(i) for i in d.items()])
# 'a=Apple,b=ball,c=cat'
If you need items ordered by key, use sorted(d.items()).
def format_dict(d):
vals = list(d.values())
return "={},".join(d.keys()).format(*vals) + "={}".format(vals[-1])
d = {'a': 'Apple', 'b': 'ball', 'c': 'cat'}
format_dict(d) # -> 'a=Apple,b=ball,c=cat'
This joins all the keys into a large string containing replacement fields that we then format passing the dict values as args. There wasn't a trailing replacement field so we concatenate the last value in the dictionary to our large string.
For anyone coming here looking for a way to explicitly extract the dictionary keys and values (e.g. if further formatting is required):
d = {'a':'Apple','b':'ball','c':'cat'}
res = ','.join(f'{k}={v}' for k, v in d.items())
# --> a=Apple, b=ball, c=cat
(uses python 3.6+ f-strings)

Get rid of NaN as key in python dictionary

I have a dictionary in which one key is a NaN, and I want to delete the key and its corresponding value. I have tried this:
from math import isnan
clean_dict = filter(lambda k: not isnan(k), dict_HMDB_ID)
but the clean_dict is not a dictionary. I want to output it from python, but I get ''
filter doesn't return a dictionary. It returns a list in Python 2 and a filter object in Python 3.
You can use dict.pop:
d = {'a': 1, 'b': 2}
print(d)
# {'a': 1, 'b': 2}
d.pop('b')
print(d)
# {'a': 1}
And in your specific case,
dict_HMDB_ID.pop(float('NaN'))
For the sake of completeness. it could be done with a dictionary comprehension but there is no point in iterating since keys are unique anyway
clean_dict = {k: v for k, v in dict_HMDB_ID.items() if not math.isnan(k)}
If you insist on using filter here (you really shouldn't) you will need to:
pass it dict_HMDB_ID.items() so it will keep the original values
provide a custom function because it will now operate on (key, value) tuples.
transform the returned filter object (it will contain an iterator with (key, value) tuples) back to a dictionary
import math
dict_HMDB_ID = {1: 'a', float('Nan'): 'b'}
clean_dict = dict(filter(lambda tup: not math.isnan(tup[0]), dict_HMDB_ID.items()))
print(clean_dict)
# {1: 'a'}
I should probably mention that the first approach (.pop) directly modifies the dict_HMDB_ID while the other two create a new dictionary. If you wish to use .pop and create a new dictionary (leaving dict_HMDB_ID as it is) you can create a new dictionary with dict:
d = {'a': 1, 'b': 2}
new_d = dict(d)
new_d.pop('b')
print(d)
# {'b': 2, 'a': 1}
print(new_d)
# {'a': 1}
you could do:
from math import nan
dict_HMDB_ID.pop(nan)
clean_dict = dict_HMDB_ID
or the other way around if you wna to preserve dict_HMDB_ID
from math import nan
clean_dict = dict(dict_HMDB_ID)
clean_dict.pop(nan)

How to reduce the sets in dict values using comprehension?

I have
x = {'a':set([1]) , 'b':set([2]), 'c':set([3]) }
It is guaranteed that there is only one element in the set. I need to convert this to
{'a': 1, 'c': 3, 'b': 2}
Following works:
x1 = {k:x[k].pop() for k in x.keys()} OR
x1 = {k:next(iter(x[k])) for k in x.keys()}
but I am not liking it as pop() here is modifying the original collection. I need help on following.
How can I use unpacking as mentioned here within comprehension.
Is there any way, I can use functools.reduce for this.
What can be a better or Pythonic way of doing this overall?
If you want to do this with an unpacking, that'd be
{k: item for k, [item] in x.iteritems()}
In my opinion, the most readable option would be to use next and iter. Unpacking might also not be of much use since it is more of an assignment operation. (See user2357112's answer)
How about simply:
>>> {k: next(iter(v)) for k, v in x.items()}
{'a': 1, 'c': 3, 'b': 2}

Python sorting nested dictionary list

I am trying to sort a nested dictionary in Python.
Right now I have a dictionary of dictionaries. I was able to sort the outer keys using sorted on the list before I started building the dictionary, but I am unable to get the inner keys sorted at same time.
I've been trying to mess with the sorted API whereas still having problems with it.
Right now I have:
myDict = {'A': {'Key3':4,'Key2':3,'Key4':2,'Key1':1},
'B': {'Key4':1,'Key3':2,'Key2':3,'Key1':4},
'C': {'Key1':4,'Key2':2,'Key4':1,'Key3':3}};
But I would like:
myDict = {'A': {'Key1':1,'Key2':3,'Key3':4,'Key4':2},
'B': {'Key1':4,'Key2':3,'Key2':1,'Key4':1},
'C': {'Key1':4,'Key2':2,'Key3':3,'Key4':1}};
I appreciate the help!
>>> from collections import OrderedDict
>>> def sortedDict(items):
... return OrderedDict(sorted(items))
>>> myDict = {'A': {'Key3':4,'Key2':3,'Key4':2,'Key1':1},
... 'B': {'Key4':1,'Key3':2,'Key2':3,'Key1':4},
... 'C': {'Key1':4,'Key2':2,'Key4':1,'Key3':3}}
>>> sortedDict((key, sortedDict(value.items())) for key, value in myDict.items())

Removing dictionaries from a list on the basis of duplicate value of key

I am new to Python. Suppose i have the following list of dictionaries:
mydictList= [{'a':1,'b':2,'c':3},{'a':2,'b':2,'c':4},{'a':2,'b':3,'c':4}]
From the above list, i want to remove dictionaries with same value of key b. So the resultant list should be:
mydictList = [{'a':1,'b':2,'c':3},{'a':2,'b':3,'c':4}]
You can create a new dictionary based on the value of b, iterating the mydictList backwards (since you want to retain the first value of b), and get only the values in the dictionary, like this
>>> {item['b'] : item for item in reversed(mydictList)}.values()
[{'a': 1, 'c': 3, 'b': 2}, {'a': 2, 'c': 4, 'b': 3}]
If you are using Python 3.x, you might want to use list function over the dictionary values, like this
>>> list({item['b'] : item for item in reversed(mydictList)}.values())
Note: This solution may not maintain the order of the dictionaries.
First, sort the list by b-values (Python's sorting algorithm is stable, so dictionaries with identical b values will retain their relative order).
from operator import itemgetter
tmp1 = sorted(mydictList, key=itemgetter('b'))
Next, use itertools.groupby to create subiterators that iterate over dictionaries with the same b value.
import itertools
tmp2 = itertools.groupby(tmp1, key=itemgetter('b))
Finally, create a new list that contains only the first element of each subiterator:
# Each x is a tuple (some-b-value, iterator-over-dicts-with-b-equal-some-b-value)
newdictList = [ next(x[1]) for x in tmp2 ]
Putting it all together:
from itertools import groupby
from operator import itemgetter
by_b = itemgetter('b')
newdictList = [ next(x[1]) for x in groupby(sorted(mydictList, key=by_b), key=by_b) ]
A very straight forward approach can go something like this:
mydictList= [{'a':1,'b':2,'c':3},{'a':2,'b':2,'c':4},{'a':2,'b':3,'c':4}]
b_set = set()
new_list = []
for d in mydictList:
if d['b'] not in b_set:
new_list.append(d)
b_set.add(d['b'])
Result:
>>> new_list
[{'a': 1, 'c': 3, 'b': 2}, {'a': 2, 'c': 4, 'b': 3}]

Categories