Matching value of 1 dictionary with key of another dictionary using Python - python

I have 2 dictionaries. Is it possible to loop DictA's key with DictB's values, and if DictB's value has a match, it would return DictB's key.
​
Is it possible to be done?
Please give me some advice/tips. What am I doing wrong? Thank you.
Example:
A: {'WNT3A': '1732', 'RG59L': ' ', 'SCZD9': ' ', 'CD241': '6005', 'C2': '', 'RH': ' '}
B: {'': [''], '6005': ['RH50A', ' CD241', ' SLC42A1'], '603': [''], '6000': [''], '8787': ['PERRS', ' RGS9L', ' MGC26458'], '41': ['ACCN2', ' BNaC2', ' hBNaC2'], '8490': [''], '9628': [''], '5999': ['SCZD9']}
Result :
new_A: {'WNT3A': '1732', 'RG59L': ' ', 'SCZD9': '5999 ', 'CD241': '6005', 'C2': '', 'RH': ' '}​
So far, I've coded this but it only seems to return me a dictionary that is whole or a dictionary containing only dictionary B.
new_a = {}
for key in ref_dict:
for value in (map(lambda x: x.strip(), ref_dict[key][0])):
if(not fill_dict.has_key(key)):
continue
elif(ref_dict[value] != fill_dict[key]):
new_a[value] = (ref_dict[key], fill_dict[key])
print new_a
Result:
{'WNT3A': '1732', 'RG59L': '', 'SCZD9': '', 'CD241': '6005', 'C2': '', 'RH': ''}
Another code I've tried is :
new_dict = {}
for k, v in fill_dict.iteritems():
vals = []
if isinstance(v, list):
for i in v:
vals.append(ref_dict.get(i))
else:
vals.append(ref_dict.get(v))
if not vals:
continue
new_dict[k] = vals
print new_dict
Result:
{'WNT3A': [None], 'RG59L': [['']], 'SCZD9': [['']], 'CD241': [['RH50A', ' CD241', ' SLC42A1']], 'C2': [['']], 'RH': [['']]}

You can use a dict-comprehension with next() for this:
>>> {k: next((k1 for k1, v1 in B.items() if k in v1), v) for k, v in A.items()}
{'WNT3A': '1732', 'RG59L': ' ', 'SCZD9': '5999', 'CD241': '6005', 'C2': '', 'RH': ' '}
Here I've used next(<gen exp>, v), if the generator expression returned an empty iterator(i.e if none of the B's values contains the key k) then simply use the value v from A, otherwise use the key returned from the generator expression.
The above code can also be written as:
d = {}
for k, v in A.items():
for k1, v1 in B.items():
if k in v1:
d[k] = k1
break
else:
#this will be executed if no value in `B` contains `k`
d[k] = v

This will update dictionary a with the values you want:
for key_a in a:
for key_b, value_b in b.iteritems():
for item in value_b:
if item == key_a:
a[key_a] = key_b
If you need a whole new dict, then just make a copy of a and update that one.

Related

Get all the keys of a nested dict

With xmltodict I managed to get my code from xml in a dict and now I want to create an excel.
In this excel the header of a value is going to be all the parents (keys in the dict).
For example:
dict = {"name":"Pete", "last-name": "Pencil", "adres":{"street": "example1street", "number":"5", "roommate":{"gender":"male"}}}
The value male will have the header: adres/roommate/gender.
Here's a way to orgainze the data in the way your question asks:
d = {"name":"Pete", "last-name": "Pencil", "adres":{"street": "example1street", "number":"5", "roommate":{"gender":"male"}}}
print(d)
stack = [('', d)]
headerByValue = {}
while stack:
name, top = stack.pop()
if isinstance(top, dict):
stack += (((name + '/' if name else '') + k, v) for k, v in top.items())
else:
headerByValue[name] = top
print(headerByValue)
Output:
{'adres/roommate/gender': 'male',
'adres/number': '5',
'adres/street': 'example1street',
'last-name': 'Pencil',
'name': 'Pete'}

compare two dictionary and update value in first dictionary

I have question on python dict update . I have two dict as mentioned below.
dict1={1:{"partname": 'part1_item1' , 'archname':'sca_item1_rev1.0.jar','rev: '1.0', 'compname': item1},
2:{"partname": 'part1_item2' , 'archname':'sca_item2_rev2.0.jar','rev: '2.0' ,'compname': item2},
3:{"partname": 'part1_item3' , 'archname':'sca_item3_rev2.0.jar','rev: '2.0' ,'compname': item3}}
dict2={item1:{'jarversion': '1.0', 'jarname':'item1', 'partition': 'item1'},
item2:{'jarversion': '1.0', 'jarname':'item2', 'partition': 'item2'},
item1:{'jarversion': '2.0', 'jarname':'item3', 'partition': 'item3'}}
I want to compare value (rev and jarname) dict1 with dict2 , if both jatname and jar version same then i need to update in dict1 with 'overwrite': 'true'
if both version are not same and version not found then , i need to update with 'overwrite': 'false' in dict1
tried created code with dict1 as mentioned below
i=1
for root, dirs, files in os.walk(comp):
if files:
if i not in dict1.keys():
dict1[i] = {}
if '\\' in root:
subdir=root.split('\\')[1]
else:
subdir=''
dict1[i].update({"partname" : '', "archname": '', "compname":'', "rev": ''})
if subdir:
dict1[i].update({"partname" : '%s'%subdir })
dict1[i].update({"archname": '', "compname":'', "rev": ''})
for filename in files:
if filename.endswith('.jar'):
dict1[i].update({"archname": '%s'%filename,"compname": ('%s' %filename).split('sca_')[1].split('_rev')[0],"rev": ('%s' %filename).split('sca_')[1].split('_rev')[1].split('.jar')[0]})
else:
print("Unrecognised file: %s"%(filename))
i=i+1
dict2 already created.
i need to update my dict with below format.
if dict1(compname)(rev) == dict2 (jarversion)(jarname)
dict1={1:{"partname": 'part1_item1' , 'archname':'sca_item1_rev1.0.jar','rev: '1.0', 'compname': item1 , 'overwrite' :'true'}}
if dict1(compname)(rev) != dict2 (jarversion)(jarname)
dict1={1:{"partname": 'part1_item1' , 'archname':'sca_item1_rev1.0.jar','rev: '1.0', 'compname': item1 , 'overwrite' :'false'}}
Please help me how to update dict with this key:values.
Let's try this,
# create a look-up set for unique (jarname + jarversion)
look_up = {v['jarname'] + v['jarversion'] for k, v in dict2.items()}
# use dict-comprehension for updating the values back to dict1
print(
{k: {**v, **{"overwrite": v['compname'] + v['rev'] in look_up}}
for k, v in dict1.items()}
)
EDIT, older version of python
look_up = set()
for _, v in dict2.items():
look_up.add(v['jarname'] + v['jarversion'])
for k, v in dict1.items():
dict1[k].update(
{"overwrite": str(v['compname'] + v['rev'] in look_up).lower()}
)

Extract matching fileds from dictonary

is there some smarter way to extract all keys from an OrderedDict into an new dictionary?
For example: I will collect all keys matching with 'pre' into the dict 'cfg_pre'. I tried this (it works):
#!/usr/bin/env python
import collections
dl=collections.OrderedDict()
dl ={
'pre_enable': True,
'pre_path': '/usr/bin/pre_script.sh',
'pre_args': '-la -w --dir',
'post_enable': True,
'post_path': '/usr/bin/post_script.sh',
'fail_enable': True,
'fail_path': '/usr/bin/failure_script.sh',
'fail_args': '--debug 4'
}
cfg_pre = dict((k,v) for k, v in dl.items() if 'pre' in k)
cfg_post= dict((k,v) for k, v in dl.items() if 'post' in k)
cfg_fail=dict((k,v) for k, v in dl.items() if 'fail' in k)
print (cfg_pre)
print ("---")
print(cfg_post)
print ("---")
print(cfg_fail)
print ("---")
The keys in the dl-dict always starts with pre, post or fail.
Thanks ;)
EDIT -> Updated to fit your need
If you would like to generalize, I would suggest going to group by methods. Something like :
import itertools as it
#define a function to split your universe (here the beginning of your keys)
def keyfunc(key):
return key.split('_')[0]
#group by prefixes
groups = {k:list(g) for k,g in it.groupby(dl, keyfunc)}
#build your output
output = {g:[(key,dl[key]) for key in v] for g,v in groups.items()}
you will get the following output:
{'fail': [('fail_enable', True),
('fail_path', '/usr/bin/failure_script.sh'),
('fail_args', '--debug 4')],
'post': [('post_enable', True), ('post_path', '/usr/bin/post_script.sh')],
'pre': [('pre_enable', True),
('pre_path', '/usr/bin/pre_script.sh'),
('pre_args', '-la -w --dir')]}
I would say that three lines is short enough for such a problem.
It would be a little cleaner with dict comprehensions:
cfg_pre = {k: v for k, v in dl.items() if 'pre' in k}
cfg_post = {k: v for k, v in dl.items() if 'post' in k}
cfg_fail = {k: v for k, v in dl.items() if 'fail' in k}
You could also remove the redundant data like this:
cfg_pre = {k.replace('pre_', ''): v for k, v in dl.items() if 'pre' in k}
cfg_post = {k.replace('post_', ''): v for k, v in dl.items() if 'post' in k}
cfg_fail = {k.replace('fail_', ''): v for k, v in dl.items() if 'fail' in k}
The dictionaries will be more consistent and the information about pre, post and fail will be stored only in the variable name:
cfg_pre = {'args': '-la -w --dir', 'enable': True, 'path': '/usr/bin/pre_script.sh'}
cfg_post = {'enable': True, 'path': '/usr/bin/post_script.sh'}
cfg_fail = {'args': '--debug 4', 'enable': True, 'path': '/usr/bin/failure_script.sh'}

How can I merge members of a list in python?

CURRENT output:
['test1.txt StatusCode: 123', 'test2.txt StatusCode: 726', 'test1.txt CompanyID: abc']
DESIRED output:
['test1.txt StatusCode: 123 CompanyID: abc', 'test2.txt StatusCode: 726']
Please try the following code. It works for your sample.
current_output = ['test1.txt StatusCode: 123', 'test2.txt StatusCode: 726', 'test1.txt CompanyID: abc']
d = dict()
order = []
for item in current_output:
k,v = item.split(' ', 1)
if k not in order:
order.append(k)
d[k] = d.get(k, []) + [v]
desired_output = ["%s %s" % (k, ' '.join(d[k])) for k in order]
print desired_output
Maybe you can get the last elem of the list, split it and then append this to the others string elems

flat delimited list to nested multilevel list

I am trying to make nested list from flat delimited list.
As an example:
L1=[
'YYYYY', 'OPEN', ' 111', ' 222', 'CLOSE',
'XXXX','OPEN', ' 333', ' 444', 'OPEN', ' 555', ' 666', 'CLOSE','CLOSE'
]
How to get nested multilevel list:
L2=
[
['YYYYY',
' 111',
' 222',
],
['XXXX',
' 333',
[' 444',
' 555',
' 666',
]
]
]
Use a stack:
def build_multilevel(entries):
result = []
stack = [result]
for i, entry in enumerate(entries):
if entry == 'OPEN':
# convert last element of the top-most list on the stack
# to a new, nested list, and push that new list on top
stack[-1][-1] = [stack[-1][-1]]
stack.append(stack[-1][-1])
elif entry == 'CLOSE':
stack.pop()
else:
stack[-1].append(entry)
return result
Demo:
>>> L1=[
... 'YYYYY', 'OPEN', ' 111', ' 222', 'CLOSE',
... 'XXXX','OPEN', ' 333', ' 444', 'OPEN', ' 555', ' 666', 'CLOSE','CLOSE'
... ]
>>> def build_multilevel(entries):
... result = []
... stack = [result]
... for i, entry in enumerate(entries):
... if entry == 'OPEN':
... # convert last element of the top-most list on the stack
... # to a new, nested list, and push that new list on top
... stack[-1][-1] = [stack[-1][-1]]
... stack.append(stack[-1][-1])
... elif entry == 'CLOSE':
... stack.pop()
... else:
... stack[-1].append(entry)
... return result
...
>>> build_multilevel(L1)
[['YYYYY', ' 111', ' 222'], ['XXXX', ' 333', [' 444', ' 555', ' 666']]]
def flat_list(_list):
"""
:param _list:
:return:
"""
res = []
if type(_list) is list:
for item in _list:
if type(item) is not list:
res.append(item)
else:
[res.append(x) for x in flat_list(item)]
else:
res.append(_list)
return res

Categories