zeeman
zeeman

Reputation: 185

Comparing the elements in lists

I am using the following script to compare the elements in two separate lists in Python3. If an element matches e.g. element [0] from list one matches element [0] from list two then the variable c is incremented by one. If the element does not match but the value is in the list then a different variable d is incremented.

I have put the code together but it is rather long and wanted to know if it could be condensed in some way.

a = [1,2,3,4]
b = [2,1,3,4]
c = 0
d = 0

if a[0] == b[0]:
    c += 1
elif a[0] == b[1] or a[0] == b[2] or a[0] == b[3]:
    d += 1

if a[1] == b[1]:
    c += 1
elif a[1] == b[0] or a[1] == b[2] or a[1] == b[3]:
    d += 1

if a[2] == b[2]:
    c += 1
elif a[2] == b[0] or a[2] == b[1] or a[2] == b[3]:
    d += 1

if a[3] == b[3]:
    c += 1
elif a[3] == b[0] or a[3] == b[1] or a[3] == b[2]:
    d += 1

Upvotes: 0

Views: 193

Answers (4)

Mehdi
Mehdi

Reputation: 4318

a = [1,2,3,4]
b = [2,1,3,4]

match = [a[i] == b[i] for i in range(len(a)) if a[i] in b]
c = sum(match)
d = len(match)-c

In this code match consists of boolean values, for matchings locations per members in the intersection of a and b.

This code will perform similarly to what was asked in the question. However, if the intention is to use it like mastermind game, this won't work. For example, if a=[1,2,3,4] and b=[4,4,4,4] the matching indicator must be: 1/1. The following code would do:

a = [1,2,3,4]
b = [4,4,4,4]

c = sum([a[i] == b[i] for i in range(len(a)) if a[i] in b])
d = sum([min(b.count(item), a.count(item)) for item in set(a)]) - c

Similar to the first guess in following game screenshot:

masetermind example

Upvotes: 1

MSeifert
MSeifert

Reputation: 152647

Yes, it can be condensed by using a for-loop and you can also make it more performant by doing the elseif (in Python this is called elif) check on a set.

a = [1,2,3,4]
b = [2,1,3,4]
c = 0
d = 0

b_set = set(b)
for item_from_a, item_from_b in zip(a, b):
    if item_from_a == item_from_b:
        c += 1
    elif item_from_a in b_set:
        d += 1

With zip one iterates over both lists at once, so it will in the first iteration access the first element from a and b (i.e. 1 and 2) in the second iteration it will access the second element from both lists (2 and 1) and so on. You could also write it as loop over the indices (it's not as "clean" as using zip but maybe easier to understand):

for idx in range(len(a)):
    item_from_a = a[idx]
    item_from_b = b[idx]
    if item_from_a == item_from_b:
        c += 1
    elif item_from_a in b_set:
        d += 1

The loop body itself should be fairly straightforward but please leave a comment if some part needs more explanation.

Upvotes: 0

Néstor
Néstor

Reputation: 351

Instead of the elif statement you can use in. Let's look an example:

I have this list: a = [1, 2, 3]. 0 in areturns False but 1 in a returns True.

So, your code will look like this:

a = [1,2,3,4]
b = [2,1,3,4]
c = 0
d = 0

if a[0] == b[0]:
    c += 1
elif a[0] in b:
    d += 1

if a[1] == b[1]:
    c += 1
elif a[1] in b:
    d += 1

if a[2] == b[2]:
    c += 1
elif a[2] in b:
    d += 1

if a[3] == b[3]:
    c += 1
elif a[3] in b:
    d += 1

Upvotes: 0

N M
N M

Reputation: 616

You can just do this.

c = [e[0]==e[1] for e in [*zip(a,b)]].count(True)
d = [e in b for e in a].count(True) - c

Upvotes: 0

Related Questions