-4

I was trying to extract unique items from a list in same order as present. I tried the following but it doesn't work. Can anyone tell me what is wrong?Thanks.

b = []
a = [10, 20, 340, 20, 10]
b = [i for i in a if i not in b]
print a

Edit:I had already seen similar ques to achieve this task.I wanted to know what was wrong in my code.

Div Jain
  • 61
  • 10
  • 2
    The reference to `b` is not updated until after your list comprehension has finished, meaning that you're checking against an empty list each iteration. – MatsLindh Jul 22 '17 at 15:32
  • In particular, please see [the answer by Python core developer Raymond Hettinger](https://stackoverflow.com/a/39835527/4014959) in the linked question. – PM 2Ring Jul 22 '17 at 16:10

5 Answers5

2

Do not use list comprehension, just use this simple for loop to achieve what you want:

b = []
a = [10, 20, 340, 20, 10]
for i in a:
    if i not in b:
        b.append(i)

Output:

>>> b
[10, 20, 340]
ettanany
  • 19,038
  • 9
  • 47
  • 63
  • It's inefficient. – caot Jul 22 '17 at 15:41
  • @caot I commented on your first answer but I did not downvote it, someone else did, so please let me know why did you downvote my answer? what's your efficient answer? Thanks! – ettanany Jul 22 '17 at 15:44
  • @caot You've removed your answer where you were using `set()` but set does not guarantee the same order, what do you suggest as efficient way to doing this? – ettanany Jul 22 '17 at 15:48
  • If `a` is small, and only has a few dupes, it's ok to use a list for dupe testing, but it's generally _much_ more efficient to use a set because the `in` test of a list has to perform a linear scan of the list until it finds a match, which means that on average it has to scan half the list elements for every test you make. However, the OP wants to preserve order, so we'd need to have a set to catch dupes and a list for the final output, which obviously consumes more RAM. – PM 2Ring Jul 22 '17 at 15:53
  • The OrderedDict approach is probably a little faster, since it can perform its loops at C speed, but it still needs to use extra temporary RAM to build the dict, and IIRC an OrderedDict uses more RAM than a plain dict (which in turn uses more RAM than a set) because it needs some way to maintain key order. FWIW, in Python 3.6, a plain dict preserves key insertion order, and it's smaller than the plain dict in previous versions, however, the fact that it preserves order is currently an implementation detail that we aren't supposed to rely on... – PM 2Ring Jul 22 '17 at 15:54
1
from collections import OrderedDict


a = [10, 20, 340, 20, 10]
b = list(OrderedDict.fromkeys(a))
print(b)

# python /tmp/wat.py
# [10, 20, 340]
offby1
  • 6,767
  • 30
  • 45
1

Your new array, b, contains no elements at the point where not in b is evaluated.

Python first creates a new list as per your list comprehension, and then assigns it to b.

There are many, many different ways to achieve this. Stackoverflow and the internet have a lot of solutions. I favour readable solutions such as:

list1 = [1,2,3,2,3,1,5,4,2,3]
result = []
for i in list1:
    if i not in result:
        result.append(i)

Though that is not the most efficient approach, I value readability higher.

Alice Heaton
  • 1,140
  • 11
  • 16
0

Try this way

>>> from collections import OrderedDict
>>> a=[10,20,340,20,10]
>>> list(OrderedDict.fromkeys(a))
[10,20,340]

Order should remain same, example

>>> from collections import OrderedDict
>>> items = [1, 2, 0, 1, 3, 2]
>>> list(OrderedDict.fromkeys(items))
[1, 2, 0, 3]
Saket Mittal
  • 3,726
  • 3
  • 29
  • 49
  • 1
    "Try this way" does not explain the solution. Please try to explain what you are doing or at least link OP to the documentation of OrderedDict. – cs95 Jul 22 '17 at 15:38
-4

Can try this as well,

>>> a = [10, 20, 340, 20, 10]
>>> b=[]
>>> [b.append(i) for i in a if i not in b]
[None, None, None]
>>> b
[10, 20, 340]
Suresh
  • 5,678
  • 2
  • 24
  • 40
  • 2
    Please do not use list comprehensions like that. List comprehensions should not have side effects, and it's wasteful to create a list of `None`s that you immediately throw away. Sure, it's only a few items in this example, but in a real program `a` could contain thousand or millions of dupes. – PM 2Ring Jul 22 '17 at 15:44