Compare two list and output missing and extra element (Python) - 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])

Related

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)

Replace string in specific index in list of lists python

How can i replace a string in list of lists in python but i want to apply the changes only to the specific index and not affecting the other index, here some example:
mylist = [["test_one", "test_two"], ["test_one", "test_two"]]
i want to change the word "test" to "my" so the result would be only affecting the second index:
mylist = [["test_one", "my_two"], ["test_one", "my_two"]]
I can figure out how to change both of list but i can't figure out what I'm supposed to do if only change one specific index.
Use indexing:
newlist = []
for l in mylist:
l[1] = l[1].replace("test", "my")
newlist.append(l)
print(newlist)
Or oneliner if you always have two elements in the sublist:
newlist = [[i, j.replace("test", "my")] for i, j in mylist]
print(newlist)
Output:
[['test_one', 'my_two'], ['test_one', 'my_two']]
There is a way to do this on one line but it is not coming to me at the moment. Here is how to do it in two lines.
for two_word_list in mylist:
two_word_list[1] = two_word_list.replace("test", "my")

Loop through 2 list of dictionaries

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

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.

Exclude items from list of lists Python

I have the next list of
testList = []
testList.append([0,-10])
testList.append([-12,122])
testList.append([13,172])
testList.append([17,296])
testList.append([-10,80])
testList.append([-16,230])
testList.append([-18, 296])
testList.append([-2, -8])
testList.append([-5,10])
testList.append([2,-4])
and another lists which contains elements from previous list:
m1 = []
m1.append([0, -10])
m1.append([13, 172])
Then I try to get a subarray from the list testList with the next statement:
[element for i, element in enumerate(testList) if i not in m1]
But I get the same list as testList.
How can I achieve this?
If you don't care about the order in the lists, you can use sets instead:
# result will be a set, not a list
not_in_testlist = set(testlist) - set(m1)
If you want the result to be a list again:
# result will be a list with a new order
not_in_m1 = list(set(testlist) - set(m1))
Be aware that using sets will lose the order of the original lists because sets are unordered types (they use hashing under the hood).
If you need to preserve the order, then Andrew Allaire's answer is correct:
# result is a list, order is preserved
not_in_testlist = [e for e in testlist if e not in m1]
The problem is with your use of enumerate. The i is just going to be an integer, and therefor never in a list that only has lists in it. Try this:
[element for element in testList if element not in m1]
Try with this:
def clean_list(my_list, exclusion_list):
new_list = []
for i in my_list:
if i in exclusion_list:
continue
else:
new_list.append(i)
return new_list

Categories