3
lst = [1, 3, 2, 1, 3, True, False, True, "apple", "banana", "mango", "apple"]

lst2 = []
for i in range(0, len(lst)):
    if lst[i] not in lst2:
        lst2.append(lst[i])
print(lst2)

Above code is to remove duplicate values. But it is also removing True value. Anyone Explain me why it's not storing True value and show me correct code.

Desired Output:

[1,3,2, True, False, “apple”, “banana”, “mango”]

Output I'm getting:

[1,3,2, False, “apple”, “banana”, “mango”]

Can anyone help me with this and explain me reason behind it. Please it would be really helpful.

Nikhil R
  • 49
  • 4

4 Answers4

3

In Python True is considered equivalent to 1 for the purposes of equality checks and mathematical operations, even though they have different types (bool vs int).

If you want to compare them as being different, a workaround might be to convert each value into a tuple with its type (because even though 1 == True, (1, int) != (True, bool)) for purposes of the comparison, and then convert them back when you're done:

>>> lst = [1, 3, 2, 1, 3, True, False, True, "apple", "banana", "mango", "apple"]
>>> for i in lst:
...     if (i, type(i)) not in lst2:
...         lst2.append((i, type(i)))
...
>>> lst2 = [i for i, _ in lst2]
>>> lst2
[1, 3, 2, True, False, 'apple', 'banana', 'mango']

If you don't care about the order, you can do this more easily with a set:

>>> [i for i, _ in {(i, type(i)) for i in lst}]
[True, 2, 3, 'mango', False, 'banana', 1, 'apple']

or if you do care about the order but still want to do it in a comprehension, you can do a bit of trickery with a dict (since dict keys are unique but unlike a set they preserve insertion order):

>>> [i for i, _ in {(i, type(i)): None for i in lst}]
[1, 3, 2, True, False, 'apple', 'banana', 'mango']
Samwise
  • 68,105
  • 3
  • 30
  • 44
1

You can use this code.


lst = [1, 3, 2, 1, 3, True, False, True, "apple", "banana", "mango", "apple"]

lst2 = []
for a in lst:
    if not any(a is i for i in lst2):
        lst2.append(a)

print(lst2)

OUTPUT [1, 3, 2, True, False, 'apple', 'banana', 'mango']

codester_09
  • 5,622
  • 2
  • 5
  • 27
  • 1
    Careful using `is` like this -- for this particular case it should work, but for different types of items they might be identical but not have the same `id`. Try for example `[1] is [1]` vs `[1] == [1]`. – Samwise Jun 25 '22 at 14:17
  • @Samwise Yeah I know, But I think integer, string, bool, or float type elements always return `True` using `is` keyword. – codester_09 Jun 25 '22 at 14:21
  • 1
    Not necessarily; the rules change for ints above a certain value, for example, and in any case it's implementation-specific so you can't (or at least shouldn't) rely on that behavior. – Samwise Jun 25 '22 at 14:24
  • Check out: https://stackoverflow.com/questions/306313/is-operator-behaves-unexpectedly-with-integers I feel like a dupe of this gets asked roughly every week, otherwise I wouldn't know about it :) – Samwise Jun 25 '22 at 14:25
  • @Samwise post say 257 is 257 is True. – codester_09 Jun 25 '22 at 14:30
  • 1
    Not always. Do for example `lst = [257]` and then `lst.append(257)` and then `lst[0] is lst[1]`. But then it behaves differently if you do `lst = [257, 257]`. So your code that dedupes the list will have a bug that depends entirely on how you built the list. Confusing, right? That's why you don't want to use `is` in your code when comparing two non-singleton objects; you will end up with bugs that are VERY hard to debug because those two lists *look* the same but aren't. – Samwise Jun 25 '22 at 14:35
0

Like @Samwise said, when python compares booleans it actually sets them to integers: True == 1 and False == 0. You can try to process them separatly like this:

lst = [1, 3, 2, 1, 3, True, False, True, "apple", "banana", "mango", "apple"]

lst_bools = list(set([i for i in lst if type(i) == bool]))
lst_not_bool = list(set([i for i in lst if type(i) != bool]))
lst2 = lst_bools + lst_not_bool
Ilya
  • 730
  • 4
  • 16
0

This appears to work and also retain the list order.

lst = [1, 3, 2, 1, 3, True, False, True, "apple", "banana", "mango", "apple"]
s = set((e, type(e)) for e in lst)
newlist = []
for e in lst:
    if (t := (e, type(e))) in s:
        newlist.append(t[0])
        s.remove(t)
print(newlist)

Output:

[1, 3, 2, True, False, 'apple', 'banana', 'mango']
DarkKnight
  • 19,739
  • 3
  • 6
  • 22