Reputation: 479
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
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
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
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
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