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"]
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 am trying to lookup two list of dictionaries based on matching keys. If the keys and values match between any dictionaries, I want to copy key value pairs from second dictionary to the first one and return it as an output. But if no match is found, the dictionary should be returned as reject. Below is an example of what I want to do and what I have coded. I am able to get my results but I want to know if there is a better way to do this.
input_list = [{'a':1, 'b': 2, 'c':3},
{'a':4, 'b': 5, 'c':6},
{'a':7, 'b': 8, 'c':9}]
ref_list = [{'a':1, 'b': 2, 'd':3, 'e': 10},
{'a':4, 'b': 5, 'd':6, 'e': 11}]
matching_cols = ['a','b']
copy_over_cols = ['d','e']
expected_output_list = [{'a':1, 'b': 2, 'c':3, 'd':3, 'e':10,},
{'a':4, 'b': 5, 'c':6, 'd':6, 'e':11,}]
expected_reject_list = [{'a':7, 'b': 8, 'c':9}]
#What I have coded so far
def lookup_dict(input_list,ref_list,matching_cols,copy_over_cols):
output_list = []
reject_list = []
for input_dict in input_list:
match_cols_dict = dict(tuple((col,input_dict[col]) for col in matching_cols))
matched = False
copy_over_items = {}
for ref_dict in ref_list:
check_cols_dict = dict(tuple((col,ref_dict[col]) for col in matching_cols))
if match_cols_dict == check_cols_dict:
matched = True
copy_over_items = dict((tuple((col,ref_dict[col]) for col in copy_over_cols)))
break
if matched == True:
input_dict.update(copy_over_items)
output_list.append(input_dict)
else:
reject_list.append(input_dict)
return output_list, reject_list
output_list, reject_list = lookup_dict(input_list,ref_list,matching_cols,copy_over_cols)
print("output - ", output_list, "reject - ", reject_list)
Your help is greatly appreciated. :)
Try this:
output_list = list()
reject_list = list()
for i in input_list:
matches = [d for d in ref_list if all(i[c]==d[c] for c in matching_cols)]
if len(matches)>0:
j = matches[0]
output_list.append({**i, **{k: j[k] for k in copy_over_cols}})
else:
reject_list.append(i)
>>> output_list
[{'a': 1, 'b': 2, 'c': 3, 'd': 3, 'e': 10},
{'a': 4, 'b': 5, 'c': 6, 'd': 6, 'e': 11}]
>>> reject_list
[{'a': 7, 'b': 8, 'c': 9}]
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))
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}
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.