0

I have a list1 containing different integers. Now, I want to create a second list (list2), that contains all elements of list1 without doubles. And I want to create list2 with list comprehension, without the need of defining it first as an empty list:

list1 = [3,3,2,1,5,6,1,5,7]
list2 = [i for i in list1 if i not in list2]
print(list2)

That case would be perfect for set(), I know. But why it is not working with a list comprehension?

In these threads I found, that my list2-syntax should be fine:

Both top voted answers suggest a syntax like

[y for y in a if y not in b]
taha
  • 722
  • 7
  • 15
  • 3
    Simple - the list comprehension evaluates _before_ the assignment to `list2` – Green Cloak Guy Aug 03 '20 at 03:58
  • So it is not possible to solve this situation with a list comprehension? So where is the difference between my situation and the suggested syntax in the top voted answers? – laura.neukamp Aug 03 '20 at 04:00
  • 1
    This will throw a `NameError`, because `list2` does not exist when the list comprehension is being evaluated. more generally, you cannot refer to the resulting list in a list comprehension, list comprehensions and other comprehension constructs are not "one-line for loops", and you shouldn't think of them as such. They are for expressing *mapping/filtering* operations that result in a new container or iterable. – juanpa.arrivillaga Aug 03 '20 at 04:22
  • Does this answer your question? [Removes duplicates from nested list without use of set](https://stackoverflow.com/questions/63223521/removes-duplicates-from-nested-list-without-use-of-set) – stovfl Aug 03 '20 at 07:00

2 Answers2

1

It's because you're defining list2's contents self-referentially. While syntactically it's correct, semantically it's meaningless - list2 isn't defined yet when you refer to it in the filter/guard part of the list comprehension.

sbw
  • 46
  • 4
  • A similar question was asked here: https://stackoverflow.com/questions/2638478/recursive-list-comprehension-in-python – sbw Aug 03 '20 at 04:23
  • when I define list2 before using the list comprehension, there are still double elements in list2: list1 = [3,3,2,1,5,6,1,5,7] list2 = [i for i in list1 if i not in list2] print(list2) – laura.neukamp Aug 03 '20 at 04:23
  • 1
    @laura.neukamp of course, because creating another list object doesn't modify list2, why would it? Again, list comprehensions are declarative constructs that describe a mapping/filtering operations to produce a new list object – juanpa.arrivillaga Aug 03 '20 at 04:24
  • 1
    @juanpa.arrivillaga: YEAH! Now I got the point! That is so logical and clear. Thank You for this explanation. – laura.neukamp Aug 03 '20 at 04:31
0

I'm not 100% sure but i believe the list isn't fully populated until the comprehension is complete.

You could simply do this if you were able to not use list comprehension

List(Set(list1))

Another option (not what you wanted either)

list1 = [3,3,2,1,5,6,1,5,7]
list2 = []
for itm in list1:
    if itm not in list2:
        list2.append(itm)
Lewis Morris
  • 1,916
  • 2
  • 28
  • 39
  • of course, I know. But I want to unterstand why it is not possible with a list comprehension in my intendet way? – laura.neukamp Aug 03 '20 at 04:15
  • Your checking if its contained in list2 but I believe list2 hasn't been populated yet, not until the comprehension is complete. – Lewis Morris Aug 03 '20 at 04:19
  • together with the answer of @juanpa.arrivillaga, this is the solution. And now I understand my problem and my error in thinking. Should always remember to write code I unterstand and I can read. Thank You Lews Morris! – laura.neukamp Aug 03 '20 at 04:34
  • Don't forget to accept the answer if it helped you :) – Lewis Morris Aug 03 '20 at 04:40