Loop through 2 list of dictionaries - python

I have this 2 list of dictionaries, I was trying to print out all the names from list1 if they are not found in list2.
list1=[{'name':'A','color':'1'},
{'name':'B','color':'2'}]
list2=[{'name':'A','color':'3'},
{'name':'C','color':'1'}]
for item in list1:
for ii in list2:
if item['name'] != ii['name']:
print item['name']
The output I'm getting is
A
B
B
I expected it to print B because there's not b in list2. Not sure what I'm doing wrong...any help would be appreciated.
Thanks

That's (obviously) not the logic of your code. You iterate through all combinations of names, and print the one from list1 every time it doesn't match any name in list2.
Instead, don't print it until you know it is a mismatch for all of those names:
for item in list1:
found = False
for ii in list2:
if item['name'] == ii['name']:
found = True
if not found:
print item['name']
This is the direct change to your implementation. There are one-liners that can do this using comprehensions, all, and other Python capabilities.

You iterate over and print in every cases where the match is not found.
You can instead use a lookup in a set which is more effective:
for x in list1:
if x['name'] not in {y['name'] for y in list2}:
print(x['name'])
Using all(), you can do:
for x in list1:
if all(x['name'] != y['name'] for y in list2):
print(x['name'])

Currently in your double for loop you print item['name'] for a mismatch between any two elements of list1 and list2, which is not what you want.
Instead you can convert the names in both lists to a set and take the set difference
list1=[{'name':'A','color':'1'},
{'name':'B','color':'2'}]
list2=[{'name':'A','color':'3'},
{'name':'C','color':'1'}]
#Iterate through both lists and convert the names to a set in both lists
set1 = {item['name'] for item in list1}
set2 = {item['name'] for item in list2}
#Take the set difference to find items in list1 not in list2
output = set1 - set2
print(output)
The output will be
{'B'}

If the names are unique in list1, you can use a set:
list1=[{'name':'A','color':'1'},
{'name':'B','color':'2'}]
list2=[{'name':'A','color':'3'},
{'name':'C','color':'1'}]
set1 = set(d['name'] for d in list1)
missingNames = set1.difference(d['name'] for d in list2) # {'B'}
If they are not unique and you want to match number of instances, you can do it with Counter from collections:
from collections import Counter
count1 = Counter(d['name'] for d in list1)
count2 = Counter(d['name'] for d in list2)
missingNames = list((count1-count2).elements()) # ['B']
With Counter, if you had two entries in list1 with name 'A', then the output would have been ['A','B'] since only one of the two 'A' in list1 would find a match in list2

Related

concentrate 2 lists in python based on a shared substring

I have two lists, for example they look something like this:
list1 = ["Time1Person001", "Time1Person002", "Time1Person003", "Time1Person004", "Time1Person005"]
list2 = ["Time2Person001", "Time2Person003", "Time2Person004", "Time2Person007"]
I want to create a third list that contains only strings that share a substring of the last 3 charachters, so the output should be:
list3 = ["Time1Person001", "Time1Person003", "Time1Person004", "Time2Person001", "Time2Person003", "Time2Person004"]
Efficient way to do it?
Thanks!
Create a set of the common endings then filter each list by that set.
list1 = ["Time1Person001", "Time1Person002", "Time1Person003", "Time1Person004", "Time1Person005"]
list2 = ["Time2Person001", "Time2Person003", "Time2Person004", "Time2Person007"]
endings = set(v[-3:] for v in list1) & set(v[-3:] for v in list2)
list3 = [v for v in list1+list2 if v[-3:] in endings]
Is this what you're after:
list3 = [x for x in list1 for y in list2 if x[-3:] == y[-3:]]

Easier way to check if an item from one list of tuples doesn't exist in another list of tuples in python

I have two lists of tuples, say,
list1 = [('item1',),('item2',),('item3',), ('item4',)] # Contains just one item per tuple
list2 = [('item1', 'd',),('item2', 'a',),('item3', 'f',)] # Contains multiple items per tuple
Expected output: 'item4' # Item that doesn't exist in list2
As shown in above example I want to check which item in tuples in list 1 does not exist in first index of tuples in list 2. What is the easiest way to do this without running two for loops?
Assuming your tuple structure is exactly as shown above, this would work:
tuple(set(x[0] for x in list1) - set(x[0] for x in list2))
or per #don't talk just code, better as set comprehensions:
tuple({x[0] for x in list1} - {x[0] for x in list2})
result:
('item4',)
This gives you {'item4'}:
next(zip(*list1)) - dict(list2).keys()
The next(zip(*list1)) gives you the tuple ('item1', 'item2', 'item3', 'item4').
The dict(list2).keys() gives you dict_keys(['item1', 'item2', 'item3']), which happily offers you set operations like that set difference.
Try it online!
This is the only way I can think of doing it, not sure if it helps though. I removed the commas in the items in list1 because I don't see why they are there and it affects the code.
list1 = [('item1'),('item2'),('item3'), ('item4')] # Contains just one item per tuple
list2 = [('item1', 'd',),('item2', 'a',),('item3', 'f',)] # Contains multiple items per tuple
not_in_tuple = []
OutputTuple = [(a) for a, b in list2]
for i in list1:
if i in OutputTuple:
pass
else:
not_in_tuple.append(i)
for i in not_in_tuple:
print(i)
You don't really have a choice but to loop over the two lists. Once efficient way could be to first construct a set of the first elements of list2:
items = {e[0] for e in list2}
list3 = list(filter(lambda x:x[0] not in items, list1))
Output:
>>> list3
[('item4',)]
Try set.difference:
>>> set(next(zip(*list1))).difference(dict(list2))
{'item4'}
>>>
Or even better:
>>> set(list1) ^ {x[:1] for x in list2}
{('item4',)}
>>>
that is a difference operation for sets:
set1 = set(j[0] for j in list1)
set2 = set(j[0] for j in list2)
result = set1.difference(set2)
output:
{'item4'}
for i in list1:
a=i[0]
for j in list2:
b=j[0]
if a==b:
break
else:
print(a)

Return matching strings from two lists based on last 4 characters

list1 = ['1_Maths','2_Chemistry','10.1_Geography','12_History']
list2 = ['1_Maths', '2_Physics', '3_Chemistry','11.1_Geography','13_History']
I want to produce two outputs from list1 and list2 based on last 4 characters.
lists = [item for itm in list1 if itm in list2]
The above only prints 1_Maths. Cannot think of a way to produce all the matching subjects.
last_4char = [sub[ : -4] for sub in list1]
This could be an idea but I'm not sure how I can implement this to product the exact results from list1/2
Output
print(new_list1) = ['1_Maths','2_Chemistry','10.1_Geography','12_History']
print(new_list2) = ['1_Maths', '3_Chemistry','11.1_Geography','13_History']
Try this:
def common_4_last(list1, list2):
return [[i for i in list1 if i[-4:] in {k[-4:] for k in list2}], [i for i in list2 if i[-4:] in {k[-4:] for k in list1}]
This will result to a list with 2 elements, one list for items form list1 and a second list for items from list2 that fit the criteria of common last 4
You can run the function for any pair of lists
For example for your given list1 and list2 result will be:
common_4_last(list1, list2)
[['1_Maths', '2_Chemistry', '10.1_Geography', '12_History'], ['1_Maths', '3_Chemistry', '11.1_Geography', '13_History']]
If you want the first list you can get it by
common_4_last(list1, list2)[0] and the same for second list

Python trouble with matching tuples

For reference this is my code:
list1 = [('10.180.13.101', '10.50.60.30', 'STCMGMTUNIX01')]
list2 = [('0.0.0.0', 'STCMGMTUNIX01')]
for i in list1:
for j in list2:
for k in j:
print (k)
if k.upper() in i:
matching_app.add(j)
for i in matching_app:
print (i)
When I run it, it does not match. This list can contain two or three variables and I need it to add it to the matching_app set if ANY value from list2 = ANY value from list1. It does not work unless the tuples are of equal length.
Any direction to how to resolve this logic error will be appreciated.
You can solve this in a few different ways. Here are two approaches:
Looping:
list1 = [('10.180.13.101', '10.50.60.30', 'STCMGMTUNIX01')]
list2 = [('0.0.0.0', 'STCMGMTUNIX01')]
matches = []
for i in list1[0]:
if i in list2[0]:
matches.append(i)
print(matches)
#['STCMGMTUNIX01']
List Comp with a set
merged = list(list1[0] + list2[0])
matches2 = set([i for i in merged if merged.count(i) > 1])
print(matches2)
#{'STCMGMTUNIX01'}
I'm not clear of what you want to do. You have two lists, each containing exactly one tuple. There also seems to be one missing comma in the first tuple.
For finding an item from a list in another list you can:
list1 = ['10.180.13.101', '10.50.60.30', 'STCMGMTUNIX01']
list2 = ['0.0.0.0', 'STCMGMTUNIX01']
for item in list2:
if item.upper() in list1: # Check if item is in list
print(item, 'found in', list1)
Works the same way with tuples.

Compare two list and output missing and extra element (Python)

I've 2 lists(sorted) of prefix and would like to compare it in Python so that I can output which element in the original list was missing and which was added.
Eg.
list1_original = ['1.1.1.1/24','2.2.2.2/24','3.3.3.3/24','4.4.4.4/24']
list2 = ['3.3.3.3/24','4.4.4.4/24','5.5.5.5/24','6.6.6.6/24']
I want to compare the 2 lists and output the add/remove element in list1_original. ie:
1.1.1.1/24, 2.2.2.2/24 = missing
5.5.5.5/24, 6.6.6.6/24 = added
If there is no duplicates in given lists you may use sets and their "-" operator:
list1 = ['1.1.1.1/24', '2.2.2.2/24', '3.3.3.3/24', '4.4.4.4/24']
list2 = ['3.3.3.3/24', '4.4.4.4/24', '5.5.5.5/24', '6.6.6.6/24']
set1 = set(list1)
set2 = set(list2)
missing = list(sorted(set1 - set2))
added = list(sorted(set2 - set1))
print('missing:', missing)
print('added:', added)
this prints
missing: ['1.1.1.1/24', '2.2.2.2/24']
added: ['5.5.5.5/24', '6.6.6.6/24']
With sets you can compare lists:
missing = set(list1_original).difference(list2)
added = set(list2).difference(list1_original)
Keep in mind that the output is a set. To cast the output into a list you can use list(missing).
You can get the result using a loop and some conditional statements.
list1 = ['1.1.1.1/24', '2.2.2.2/24', '3.3.3.3/24', '4.4.4.4/24']
list2 = ['3.3.3.3/24', '4.4.4.4/24', '5.5.5.5/24', '6.6.6.6/24']
for i in list1:
if i in list2:
print("added",i)
else:
print("missing",i)
missing 1.1.1.1/24
missing 2.2.2.2/24
added 3.3.3.3/24
added 4.4.4.4/24
Same thing can also be framed like so,
[print("added",i) if i in list2 else print("missing",i) for i in list1]
This will work regardless duplicate values without sorted().
>>> def finder(arr1,arr2):
for i in range(len(arr1)):
if arr1[i] not in arr2:
print("missing",arr1[i])
for j in range(len(arr2)):
if arr2[j] not in arr1:
print("added",arr2[j])

Categories