How to get the key values present commonly between two lists?

Viewed 89

I am trying to get the key values commonly present in both first_list and second_list as below,first_list and second_list has X and Z as the common keys,I want to get the values corresponding to X and Z and create a final dictionary as show in EXPECTED OUTPUT BELOW,I have the current and expected output,can someone provide guidance on what is wrong here?

first_list = [{'W':['xyz','abc','def']},{'X':['1','2','3']},{'Y':['4','5','6']},{'Z':['1','5','7']}]

second_list = [{'X':True},{'Z':True}]


first_list_keys,second_list_keys = [],[]
for item in first_list:
    for key,value in item.items():
        print (key,value)
        first_list_keys.append(key)

for item in second_list:
    for key,value in item.items():
        print (key,value)
        second_list_keys.append(key)
print(first_list_keys,second_list_keys)
c = set(first_list_keys).intersection(second_list_keys)

print (c)
final_dict = {}
for item in c:
    item_dict = {}
    for data in first_list:
        for key,value in data.items():
            print (key,value)
            if key == item:
                print ('==================')
                print (value)
                item_dict['deps'] = value


                for item in c:
                    for data in second_list:
                        for key,value in data.items():
                            print (key,value)
                            if key == item:
                                print ('==================')
                                print (value)
                                item_dict['values'] = True
                final_dict[key] = item_dict
print (final_dict)

CURRENT OUTPUT:-

{'Z': {'deps': ['1', '5', '7'], 'values': True}}

EXPECTED OUTPUT:-

{'X':{"deps":['1','2','3'],"values": true },'Z':{"deps":['1','5','7'],"values": true }

UPDATE:-

{'W':{"deps":['xyz','abc','def'],"values": False},'X':{"deps":['1','2','3'],"values": True },'Y':{"deps":['4','5','6'],"values":False},'Z':{"deps":['1','5','7'],"values": True }
3 Answers

Here's one solution. Note that to be able to look up the keys in the second list, I first turn it into a dictionary and then work with that. This code assumes that each dictionary in either list consists of exactly one key/value pair:

first_list = [{'W':['xyz','abc','def']},{'X':['1','2','3']},{'Y':['4','5','6']},{'Z':['1','5','7']}]

second_list = [{'X':True},{'Z':True}]

result ={}

# Create a map from "second_list", where for each entry in "second_list", we pull out the one
# key/value pair contained therin and then add it to the new dictionary
second_list_map = { next(iter(kv.keys())):next(iter(kv.values())) for kv in second_list}

# For each entry in the first list...
for fentry in first_list:
    # Get the one key in the entry
    key = next(iter(fentry.keys()))
    # If this key is also in the second list...
    if key in second_list_map:
        # Add the appropriate entry to the result dictionary
        result[key] = {
            "deps": fentry[key],
            "values": second_list_map[key]
        }

print(result)

Result:

{'X': {'deps': ['1', '2', '3'], 'values': True}, 'Z': {'deps': ['1', '5', '7'], 'values': True}}

Here's the main body for the updated requirement of retaining all the values from the first list, and noting the absence of a key in the second list with 'values': False:

for fentry in first_list:
    key = next(iter(fentry.keys()))
    result[key] = {
        "deps": fentry[key],
        "values": second_list_map[key] if key in second_list_map else False
    }

Result:

{'W': {'deps': ['xyz', 'abc', 'def'], 'values': False}, 'X': {'deps': ['1', '2', '3'], 'values': True}, 'Y': {'deps': ['4', '5', '6'], 'values': False}, 'Z': {'deps': ['1', '5', '7'], 'values': True}}

You can join the two lists into a single list. Then sort the list by the dictionary keys. That will give you the keys next to each other. Check the adjacent element and if the keys match, then you can update your dictionary accordingly. If adjacent keys don't match, then set Values = False.

Here's the code to do it.

first_list = [{'W':['xyz','abc','def']},
              {'X':['1','2','3']},
              {'Y':['4','5','6']},
              {'Z':['1','5','7']}]

second_list = [{'X':True},{'Z':True}]

#combine the two lists, then sort the list by dictionary keys

combined = sorted(first_list + second_list, key=lambda d: sorted(d.keys()))

#setup a dictionary to store final result    
fs_final_dict = {}

#set index to 0
i = 0

#iterate through the dictionary and check for adjacent element

while i <= (len(combined)-1):
    if i == len(combined)-1:
        k1,v1 = [*combined[i].items()][0]
        fs_final_dict[k1] = {'deps':v1,'values':False}
        i+=1
    elif combined[i].keys() == combined[i+1].keys():
        k1,v1 = [*combined[i].items()][0]
        k2,v2 = [*combined[i+1].items()][0]
        fs_final_dict[k1] = {'deps':v1,'values':v2}
        i+=2
    else:
        k1,v1 = [*combined[i].items()][0]
        fs_final_dict[k1] = {'deps':v1,'values':False}
        i+=1
        
print (fs_final_dict)

The output will be:

{'W': {'deps': ['xyz', 'abc', 'def'], 'values': False}, 'X': {'deps': ['1', '2', '3'], 'values': True}, 'Y': {'deps': ['4', '5', '6'], 'values': False}, 'Z': {'deps': ['1', '5', '7'], 'values': True}}

A few test cases:

Test Case 1: Passed

second_list = [{'X':True},{'X':True}]

Output is:

{'W': {'deps': ['xyz', 'abc', 'def'], 'values': False}, 'X': {'deps': True, 'values': False}, 'Y': {'deps': ['4', '5', '6'], 'values': False}, 'Z': {'deps': ['1', '5', '7'], 'values': False}}

Test Case 2: Passed

second_list = [{'X':True},{'Y':True}]

{'W': {'deps': ['xyz', 'abc', 'def'], 'values': False}, 'X': {'deps': ['1', '2', '3'], 'values': True}, 'Y': {'deps': ['4', '5', '6'], 'values': True}, 'Z': {'deps': ['1', '5', '7'], 'values': False}}

Test Case 3: Passed

second_list = [{'X':True},{'W':True}]

{'W': {'deps': ['xyz', 'abc', 'def'], 'values': True}, 'X': {'deps': ['1', '2', '3'], 'values': True}, 'Y': {'deps': ['4', '5', '6'], 'values': False}, 'Z': {'deps': ['1', '5', '7'], 'values': False}}

Test Case 4: Passed

second_list = [{'W':True},{'Z':True}]

{'W': {'deps': ['xyz', 'abc', 'def'], 'values': True}, 'X': {'deps': ['1', '2', '3'], 'values': False}, 'Y': {'deps': ['4', '5', '6'], 'values': False}, 'Z': {'deps': ['1', '5', '7'], 'values': True}}

Test Case 5: Passed Even though value of W is False, I am considering a value exists and I am populating the value in the second_list rather than overriding it with True. If we should make it True, then the code has to change.

second_list = [{'W':False},{'Z':True}]

{'W': {'deps': ['xyz', 'abc', 'def'], 'values': False}, 'X': {'deps': ['1', '2', '3'], 'values': False}, 'Y': {'deps': ['4', '5', '6'], 'values': False}, 'Z': {'deps': ['1', '5', '7'], 'values': True}}

Test Case 6: Failed second_list has a key that is NOT in first_list. What do you want the code to do? Ignore key and value in second_list or store that as a new entry in final_list? The current code stores it as a new key.

second_list = [{'P':True},{'Z':True}]

{'P': {'deps': True, 'values': False}, 'W': {'deps': ['xyz', 'abc', 'def'], 'values': False}, 'X': {'deps': ['1', '2', '3'], 'values': False}, 'Y': {'deps': ['4', '5', '6'], 'values': False}, 'Z': {'deps': ['1', '5', '7'], 'values': True}}

Test Case 7: Passed second_list has a key with the value in a list. I am considering it as a value that needs to be appended to final_list. Is this correct?

second_list = [{'W':[True]},{'Z':True}]

{'W': {'deps': ['xyz', 'abc', 'def'], 'values': [True]}, 'X': {'deps': ['1', '2', '3'], 'values': False}, 'Y': {'deps': ['4', '5', '6'], 'values': False}, 'Z': {'deps': ['1', '5', '7'], 'values': True}}

CODE

first_list = [{'W':['xyz','abc','def']},{'X':['1','2','3']},{'Y':['4','5','6']},{'Z':['1','5','7']}]

second_list = [{'X':True},{'Z':True}]

first_dict = {key: value for elem in first_list for key, value in elem.items()}

second_dict = {key: value for elem in second_list for key, value in elem.items()}

newdict={key: {"dept": first_dict[key], "value": second_dict[key]} if key in list(second_dict.keys()) else {"dept": first_dict[key], "value": False} for key in list(first_dict.keys()) }

print(newdict)

output:

{'W': {'dept': ['xyz', 'abc', 'def'], 'value': False}, 'X': {'dept': ['1', '2', '3'], 'value': True}, 'Y': {'dept': ['4', '5', '6'], 'value': False}, 'Z': {'dept': ['1', '5', '7'], 'value': True}}

EXPLAINATION

first step:

first_dict = {key: value for elem in first_list for key, value in elem.items()}

here with a dict comprehension i merge all the dicts stored in first_list

output:

{'W': ['xyz', 'abc', 'def'],
 'X': ['1', '2', '3'],
 'Y': ['4', '5', '6'],
 'Z': ['1', '5', '7']}

second step:

second_dict = {key: value for elem in second_list for key, value in elem.items()}

here with a dict comprehension i merge all the dicts stored in second_list

output:

{'X': True, 'Z': True}

last step:

newdict={key: {"dept": first_dict[key], "value": second_dict[key]} for key in list(first_dict.keys()) if key in list(second_dict.keys())}

here with the last dict comprehension i generate the needed output

  1. Iterating above first_dict i check if the keys are also in second_dict
  2. if the condition occurres i create a new item in the dict, with the shared key as a key and a dict as a value, the nested dict contains under "dept" key the value from the first_dict and under the key "value" the value fron the second_dict
  3. if the condition doesn't occurres i create a new item in the dict, with the non shared key as a key and a dict as a value, the nested dict contains under "dept" key the value from the first_dict and under the key "value" the value False
Related