I'm pretty new to Python and am getting a little confused as to what you can and can't do with lists. I have two lists that I want to compare and return matching and nonmatching elements in a binary format. List1
is of constant length, while the length of List2
differs (but is always shorter than List1
).
For example:
List1 = ['dog', 'cat', 'pig', 'donkey']
List2 = ['dog', 'cat', 'donkey']
Output wanted:
List3 = [1, 1, 0, 1]
The code I have so far is:
def match_nonmatch(List1, List2):
List3 = []
for i in range(len(List1)):
for j in range(len(List2)):
if List1[i] == List2[j]:
List3.append(1)
else:
List3.append(0)
return List3
I am able to return the matches when I compare the lists, but when I include the else statement shown above to return the nonmatches I end up with a list that is way longer than it should be. For instance, when I use a list comparing 60 items, I get a list that contains 3600 items rather than 60.
I'd appreciate it if someone could explain to me the problem with my code as it currently stands and suggest how I could modify the code so it does what I want.
Use set
instead of list
. This way you can do lots of nice things:
set1 = set(['dog', 'cat', 'pig', 'donkey'])
set2 = set(['dog', 'cat', 'donkey'])
matched = set1.intersection(set2) # set(['dog', 'cat', 'donkey'])
unmatched = set1.symmetric_difference(set2) # set(['pig'])
I know it's not exactly what you asked for, but it's usually a better practice to use sets instead of lists when doing this sort of things.
More on sets here: http://docs.python.org/library/stdtypes.html#set
use the following code.
listt3=[]
for i in listt1:
if i in listt2:
listt3.append(1)
else:
listt3.append(0)
If you prefer one-liners,
listt3=[ 1 if i in listt2 else 0 for i in listt1]
You can use bitwise operation too:
List1 = ['dog', 'cat', 'pig', 'donkey']
List2 = ['dog', 'cat', 'donkey']
matching:
set(List1) & set(List2)
not matching:
set(List1) ^ set(List2)
Here is how I would do it if list2
is short:
list1 = ['dog', 'cat', 'pig', 'donkey']
list2 = ['dog', 'cat', 'donkey']
list3 = [int(val in list2) for val in list1]
print(list3)
This prints:
[1, 1, 0, 1]
If list2
is long, you could convert it to a set
first to make the code more efficient:
list1 = ['dog', 'cat', 'pig', 'donkey']
set2 = set(['dog', 'cat', 'donkey'])
list3 = [int(val in set2) for val in list1]
print(list3)
The reason your current code produces too many elements is that you call append()
on every iteration of the inner loop, and there are len(List1) * len(List2)
such iterations.
Here is how it can be fixed:
def match_nonmatch(List1, List2):
List3 = []
for i in range(len(List1)):
for j in range(len(List2)):
if List1[i] == List2[j]:
List3.append(1)
break # fix #1
else: # fix #2
List3.append(0)
return List3
Note the added break
and the fact that the else
clause is now refers to the inner for
and not the if
.
That said, I'd still use the one-liner at the top of my answer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With