I have two lists that I need to merge based on a column name that exists in both. The source is JSON.
I'm not sure how to do this, I looked at How to merge multiple dicts with same key? but that one doesn't constrain anything.
Example:
dict1 = {"a": 3, 'b': 4}
dict2 = {"a": 3, 'c': 5}
dict3 = {"a": 1, 'b': 2}
dict4 = {"a": 1, 'c': 8}
dict_result = [{"a": 3, 'b': 4, 'c': 5},{"a": 1, 'b': 2, 'c': 8}]
BR
Here try this.
dict1 = {"a": 3, 'b': 4}
dict2 = {"a": 3, 'c': 5}
dict3 = {"a": 1, 'b': 2}
dict4 = {"a": 1, 'c': 8}
def merge_dictionary(*args):
dictionary = []
dict_result=[]
app_index = 0 # append index
for dic in (args):
for item, value in dic.items():
if [item, value] not in dictionary:
dictionary.append([item, value])
for index, x in enumerate(dictionary):
if index%3==0:
dict_result.append({x[0]:x[1]})
app_index = index
else:
dict_result[app_index//3].update({x[0]:x[1]})
return dict_result
print(merge_dictionary(dict1, dict2, dict3, dict4))
Related
I want to change just Keys (not Values) in a Dictionary in Python. Is there any way to do that?
You can pop the value of the old key and reassign:
d = {'A': 1, 'B': 2, 'C': 3}
d['b'] = d.pop('B')
print(d)
# {'A': 1, 'C': 3, 'b': 2}
Note that this won't maintain the order of the keys (python 3.6+). The renamed key will be instead at the end.
maintaining order
If order is important you need to create a new dictionary
d = {'A': 1, 'B': 2, 'C': 3}
rename = {'B': 'b', 'A': 'a'}
d = {rename.get(k, k): v for k,v in d.items()}
print(d)
# {'a': 1, 'b': 2, 'C': 3}
in place modification while maintaining order
If you want to modify the dictionary in place (i.e. not creating a new object), you need to pop and reinsert all keys in order:
d = {'A': 1, 'B': 2, 'C': 3}
rename = {'B': 'b', 'A': 'a'}
keys = list(d)
for k in keys:
d[rename.get(k, k)] = d.pop(k)
print(d)
{'a': 1, 'b': 2, 'C': 3}
I have 4 dictionaries, let's call them:
dict1 , dict2 , dict3 , dict4
Example:
dict1 = {'A': 1, 'B':2}
dict2 = {'A': 3, 'C':4}
dict3 = {'B': 5, 'D':6}
dict4 = {'A': 7, 'B':8, 'C': 9, 'D':10, 'E':11}
Each dictionary level is "stronger" than those who come after it. As in, A found in dict1 will be 'stronger' than A found in dict2 in terms of precedence.
Is there a short, elegant script to create a new dictionary, assembled from all four, where each key is taken from the "strongest" dictionary that contains that key?
The result should be: dict = {'A':1, 'B':2, 'C':4, 'D:6', 'E':11}
I think the easiest/clearest approach here would be to create a new dictionary then use its update method, which overwrites existing keys. Something like this makes the precedence pretty obvious:
>>> x = {}
>>> x.update(dict4)
>>> x.update(dict3)
>>> x.update(dict2)
>>> x.update(dict1)
>>> x
{'A': 1, 'B': 2, 'C': 4, 'D': 6, 'E': 11}
Docs
You could of course make a utility of some sort for this, something like:
>>> def collapse(*dicts):
... x = {}
... for dict in dicts:
... x.update(dict)
... return x
...
>>>
>>> collapse(dict4, dict3, dict2, dict1)
{'A': 1, 'B': 2, 'C': 4, 'D': 6, 'E': 11}
(Though you'd need to remember to pass the dictionaries in the correct order.)
You could do the following (works on python 3.5 and newer):
result = {**dict4, **dict3, **dict2, **dict1}
Here's a fairly simple way for an arbitrary number of dictionaries:
dict1 = {'A': 1, 'B':2}
dict2 = {'A': 3, 'C':4}
dict3 = {'B': 5, 'D':6}
dict4 = {'A': 7, 'B':8, 'C': 9, 'D':10, 'E':11}
# strongest dictionary last
dictionaries = [dict4, dict3, dict2, dict1]
dict(i for d in dictionaries for i in d.items())
Output:
{'A': 1, 'B': 2, 'C': 4, 'D': 6, 'E': 11}
You probably want a ChainMap, which is perfect for simulating scope.
>>> import collections
>>> cm = collections.ChainMap(dict1, dict2, dict3, dict4)
>>> dict(cm)
{'A': 1, 'B': 2, 'C': 4, 'D': 6, 'E': 11}
>>> cm['A'] = 'foo'
>>> cm
ChainMap({'A': 'foo', 'B': 2}, {'A': 3, 'C': 4}, {'B': 5, 'D': 6}, {'A': 7, 'B': 8, 'C': 9, 'D': 10, 'E': 11})
>>> dict1
{'A': 'foo', 'B': 2}
Having a dict like:
x = {
'1': {'a': 1, 'b': 3},
'2': {'a': 2, 'b': 4}
}
I'd like to have a new key total with the sum of each key in the subdictionaries, like:
x['total'] = {'a': 3, 'b': 7}
I've tried adapting the answer from this question but found no success.
Could someone shed a light?
Assuming all the values of x are dictionaries, you can iterate over their items to compose your new dictionary.
from collections import defaultdict
x = {
'1': {'a': 1, 'b': 3},
'2': {'a': 2, 'b': 4}
}
total = defaultdict(int)
for d in x.values():
for k, v in d.items():
total[k] += v
print(total)
# defaultdict(<class 'int'>, {'a': 3, 'b': 7})
A variation of Patrick answer, using collections.Counter and just update since sub-dicts are already in the proper format:
from collections import Counter
x = {
'1': {'a': 1, 'b': 3},
'2': {'a': 2, 'b': 4}
}
total = Counter()
for d in x.values():
total.update(d)
print(total)
result:
Counter({'b': 7, 'a': 3})
(update works differently for Counter, it doesn't overwrite the keys but adds to the current value, that's one of the subtle differences with defaultdict(int))
You can use a dictionary comprehension:
x = {'1': {'a': 1, 'b': 3}, '2': {'a': 2, 'b': 4}}
full_sub_keys = {i for b in map(dict.keys, x.values()) for i in b}
x['total'] = {i:sum(b.get(i, 0) for b in x.values()) for i in full_sub_keys}
Output:
{'1': {'a': 1, 'b': 3}, '2': {'a': 2, 'b': 4}, 'total': {'b': 7, 'a': 3}}
from collections import defaultdict
dictionary = defaultdict(int)
x = {
'1': {'a': 1, 'b': 3},
'2': {'a': 2, 'b': 4}
}
for key, numbers in x.items():
for key, num in numbers.items():
dictionary[key] += num
x['total'] = {key: value for key, value in dictionary.items()}
print(x)
We can create a default dict to iterate through each of they key, value pairs in the nested dictionary and sum up the total for each key. That should enable a to evaluate to 3 and b to evaluate to 7. After we increment the values we can do a simple dictionary comprehension to create another nested dictionary for the totals, and make a/b the keys and their sums the values. Here is your output:
{'1': {'a': 1, 'b': 3}, '2': {'a': 2, 'b': 4}, 'total': {'a': 3, 'b': 7}}
Suppose I am give a list of dictionaries, where
dict1 = dict(a = 2, b = 5, c = 7)
dict2 = dict(c = 5, d = 5, e = 1)
dict3 = dict(e = 2, f = 4, g = 10)
list_of_dictionaries = [dict1, dict2, dict3]
How would I be able to, find the value of the highest index (aka the latest dictionary)?
So if I were to write a method to delete an item from the list of dictionaries, let's say I want to delete c from the dictionary.
How would I be able to delete the c from the second dictionary instead of the first?
The key is reversing through the list with reverse indexing (a_list[::-1]).
From there once you find any dictionary that matches the requirements alter it and quit the function or loop - hence the early returns.
This code:
def get_last(bucket,key):
for d in bucket[::-1]:
if key in d.keys():
return d[key]
return None
def set_last(bucket,key,val):
for d in bucket[::-1]:
if key in d.keys():
d[key] = val
return
def pop_last(bucket,key):
out = None
for d in bucket[::-1]:
if key in d.keys():
return d.pop(key)
dict1 = {'a': 2, 'b': 5, 'c': 7}
dict2 = {'c': 5, 'd': 5, 'e': 1}
dict3 = {'e': 2, 'f': 4, 'g': 10}
list_of_dictionaries = [dict1, dict2, dict3]
print get_last(list_of_dictionaries ,'c')
set_last(list_of_dictionaries ,'c',7)
print list_of_dictionaries
popped = pop_last(list_of_dictionaries ,'c')
print popped
print list_of_dictionaries
Gives:
5
[{'a': 2, 'c': 7, 'b': 5}, {'c': 7, 'e': 1, 'd': 5}, {'e': 2, 'g': 10, 'f': 4}]
7
[{'a': 2, 'c': 7, 'b': 5}, {'e': 1, 'd': 5}, {'e': 2, 'g': 10, 'f': 4}]
I am not exactly sure what you mean but I wan to show you a couple of things that might help:
First here is how your dictionaries should look like:
dict1 = {"a" :2, "b" : 5, "c" :7}
dict2 = {"c" :5, "d" :5, "e" :1}
dict3 = {"e" :2, "f" :4, "g" :10}
Then you asked this: "How would I be able to delete the c from the second dictionary instead of the first?"
You can do delete it this way:
del dict2["c"]
Lets say I have two dictionaries:
a = {'a': 1, 'b': 2, 'c': 3}
b = {'b': 2, 'c': 3, 'd': 4, 'e': 5}
What's the most pythonic way to find the non mutual items between the two of them such that for a and b I would get:
{'a': 1, 'd': 4, 'e': 5}
I had thought:
{key: b[key] for key in b if not a.get(key)}
but that only goes one way (b items not in a) and
a_only = {key: a[key] for key in a if not b.get(key)}.items()
b_only = {key: b[key] for key in b if not a.get(key)}.items()
dict(a_only + b_only)
seams very messy. Any other solutions?
>>> dict(set(a.iteritems()) ^ set(b.iteritems()))
{'a': 1, 'e': 5, 'd': 4}
Try with the symetric difference of set() :
out = {}
for key in set(a.keys()) ^ set(b.keys()):
out[key] = a.get(key, b.get(key))
diff = {key: a[key] for key in a if key not in b}
diff.update((key,b[key]) for key in b if key not in a)
just a bit cheaper version of what you have.
>>> a = {'a': 1, 'b': 2, 'c': 3}
>>> b = {'b': 2, 'c': 3, 'd': 4, 'e': 5}
>>> keys = set(a.keys()).symmetric_difference(set(b.keys()))
>>> result = {}
>>> for k in keys: result[k] = a.get(k, b.get(k))
...
>>> result
{'a': 1, 'e': 5, 'd': 4}
Whether this is less messy than your version is debatable, but at least it doesn't re-implement symmetric_difference.