7

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.

Rik Poggi
  • 28,332
  • 6
  • 65
  • 82
Platypus
  • 73
  • 1
  • 1
  • 3

6 Answers6

22

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

dorsh
  • 23,750
  • 2
  • 27
  • 29
10

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]

5

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) 
JJJ
  • 32,902
  • 20
  • 89
  • 102
Mahdi Shahbaba
  • 499
  • 6
  • 4
4

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.

NPE
  • 486,780
  • 108
  • 951
  • 1,012
  • Thanks for the explanation. After reading this and other replies, I will look into sets - haven't come across the concept before. – Platypus Jan 22 '12 at 11:36
  • @aix Don't you think there would be an error raised at the line of the `else` statement? – Sandip Agarwal Jan 22 '12 at 11:46
  • 1
    @SandipAgarwal: No, I don't. I've tested the code before posting and it works. `for`...`else` is valid construct in Python -- look it up. – NPE Jan 22 '12 at 11:47
  • @aix Hey, it works. Some problem on my side. Don't you think writing the one-liner is better? – Sandip Agarwal Jan 22 '12 at 11:55
  • 1
    @SandipAgarwal: I do. See the last sentence of my answer. – NPE Jan 22 '12 at 11:56
0
[int(i==j) for i, j in zip(list1, list2)]
Machavity
  • 30,841
  • 27
  • 92
  • 100
  • 4
    Welcome to Stack Overflow! Thank you for this code snippet, which might provide some limited, immediate help. A [proper explanation would greatly improve its long-term value](//meta.stackexchange.com/q/114762/206345) by showing _why_ this is a good solution to the problem, and would make it more useful to future readers with other, similar questions. Please [edit] your answer to add some explanation, including the assumptions you've made. – Machavity Mar 05 '18 at 17:52
0
>>> list1 = ['dog', 'cat', 'pig', 'donkey']; list2 = ['dog', 'cat', 'donkey']
>>> [i in list2 for i in list1]
[True, True, False, True]

Also, you should read PEP8, CamelCase names are commonly used for classes only.

pyroscope
  • 4,120
  • 1
  • 18
  • 13