i have worked out a full solution for deep intersection
def common_items_dict(d1, d2, use_set_for_list_commons=True, use_set_for_dict_key_commons=True, append_empty=False):
result = {}
if use_set_for_dict_key_commons:
shared_keys=list(set(d1.keys()).intersection(d2.keys())) # faster, order not preserved
else:
shared_keys=common_items_list(d1.keys(), d2.keys(), use_set_for_list_commons=False)
for k in shared_keys:
v1 = d1[k]
v2 = d2[k]
if isinstance(v1, dict) and isinstance(v2, dict):
result_dict=common_items_dict(v1, v2, use_set_for_list_commons, use_set_for_dict_key_commons, append_empty)
if len(result_dict)>0 or append_empty:
result[k] = result_dict
elif isinstance(v1, list) and isinstance(v2, list):
result_list=common_items_list(v1, v2, use_set_for_list_commons, use_set_for_dict_key_commons, append_empty)
if len(result_list)>0 or append_empty:
result[k] = result_list
elif v1 == v2:
result[k] = v1
return result
def common_items_list(d1, d2, use_set_for_list_commons=True, use_set_for_dict_key_commons=True, append_empty=False):
if use_set_for_list_commons:
result_list= list(set(d2).intersection(d1)) # faster, order not preserved, support only simple data types in list values
return result_list
result = []
for v1 in d1:
for v2 in d2:
if isinstance(v1, dict) and isinstance(v2, dict):
result_dict=common_items_dict(v1, v2, use_set_for_list_commons, use_set_for_dict_key_commons, append_empty)
if len(result_dict)>0 or append_empty:
result.append(result_dict)
elif isinstance(v1, list) and isinstance(v2, list):
result_list=common_items_list(v1, v2, use_set_for_list_commons, use_set_for_dict_key_commons, append_empty)
if len(result_list)>0 or append_empty:
result.append(result_list)
elif v1 == v2:
result.append(v1)
return result
def deep_commons(v1,v2, use_set_for_list_commons=True, use_set_for_dict_key_commons=True, append_empty=False):
"""
deep_commons
returns intersection of items of dict and list combinations recursively
this function is a starter function,
i.e. if you know that the initial input is always dict then you can use common_items_dict directly
or if it is a list you can use common_items_list directly
v1 - dict/list/simple_value
v2 - dict/list/simple_value
use_set_for_dict_key_commons - bool - using set is faster, dict key order is not preserved
use_set_for_list_commons - bool - using set is faster, list values order not preserved, support only simple data types in list values
append_empty - bool - if there is a common key, but no common items in value of key , if True it keeps the key with an empty list of dict
"""
if isinstance(v1, dict) and isinstance(v2, dict):
return common_items_dict(v1, v2, use_set_for_list_commons, use_set_for_dict_key_commons, append_empty)
elif isinstance(v1, list) and isinstance(v2, list):
return common_items_list(v1, v2, use_set_for_list_commons, use_set_for_dict_key_commons, append_empty)
elif v1 == v2:
return v1
else:
return None
needed_services={'group1':['item1','item2'],'group3':['item1','item2']}
needed_services2={'group1':['item1','item2'],'group3':['item1','item2']}
result=deep_commons(needed_services,needed_services2)
print(result)