Al Hill
Al Hill

Reputation: 479

List comprehension in Python (Comparing and not repeating numbers in a list)

I'm trying to write a program which takes two lists with randomly generated integer and returns a list with the number which are in both lists without any repetition, using list comprehension.

importrandom

def estaDentroDe(a, listita):
    for i in listita:
        if (i == a):
            return True
#

a = [random.randint(1,20) for i in range(20)]
b = [random.randint(1,20) for i in range(20)]

lista = []
lista = [elem_a for elem_a in a for elem_b in b if (elem_a == elem_b) if (not estaDentroDe(elem_a, lista))]

print (a)
print (b)
print (lista)

The problem is that the part of not repeating results is not working well, it filters some values but without a logical sense.

But if I don't use list comprehension, only with nested for's and if's (directly translated from the code above) it works without problem

lista = []
for elem_a in a:
    for elem_b in b:
        if (elem_a == elem_b):
            if (not estaDentroDe(elem_a, lista)):
                lista.append(elem_a)
#

It's pretty obvious there's something wrong with the list comprehension syntax but I don't understand where...


EDIT

The problem wasn't syntax but run-time. As 'lista' is empty when evaluating this clause in the list comprehension, this 'if' is always true and it doesn't filter duplicates. Instead, the 'for' version reevaluates 'lista' in each iteration so it's not empty (and it works)

I was trying to make it only with list comprehensions because I have been told so, but I didn't know about sets and it really simplify this code. I have found a solution to solve it with a list comprehension with side effects but it didn't convince me.

I have done three different approaches. Second one is pretty cute, thank you all!

from random import randint

a = [randint(1,20) for i in range(20)]
b = [randint(1,20) for i in range(20)]

lista = set([elem_a for elem_a in a if elem_a in b]) #LIST COMPREHENSION & SETS

listab = set(a) & set(b) #ONLY SETS

listac_dup = [elem_a for elem_a in a if elem_a in b] #LIST COMPREHENSION & FOR/IF
listac = []
for elem in listac_dup:
    if elem not in listac:
        listac.append(elem)

print (a)
print (b)
print (lista)
print (listab)
print (listac)

Upvotes: 0

Views: 560

Answers (4)

B. M.
B. M.

Reputation: 18668

Pythonic ways to do that are:

c= [ x for x in set(a) if x in set(b)]
# or c = set(a) & set (b) when you'll be at ease with sets.

which manage multiple elements.

with list comprehension, you have to count...

An ugly possibility :

 [x for x in [y for (i,y) in enumerate(a) if y not in a[(i+1):]] if x in b]

Upvotes: 0

Tabaene Haque
Tabaene Haque

Reputation: 574

Try this

import random
a = [random.randint(1,20) for i in range(20)]
b = [random.randint(1,20) for i in range(20)]

lista = [elem_a for elem_a in a if elem_a in b ]

print (lista)

Upvotes: 1

P.hunter
P.hunter

Reputation: 1365

import random

Z = set(random.randrange(0, 20) for I in range(0, 20))

L = set(random.randrange(0, 20) for I in range(0, 20))

new = []

for I in Z:

if I in L:

    new.append(I)

print(new)

does this solve the problem?

Upvotes: 0

wim
wim

Reputation: 363103

The second if inside your comprehension should be an and instead. Other than that, it looks correct.

However, this is a bit too complicated for a list comprehension. The for-loop version of the code is better in my opinion.

Upvotes: 1

Related Questions