Как удалить только нулевую цифру из списка python?

#python #python-3.x

#python #python-3.x

Вопрос:

Я хочу удалить 0 только из своего списка:

 >>> mylist = [0, 1, None, 2, False, 1, 0]
  

Во всех из них отсутствуют ложные элементы

 >>> list(filter(lambda x: x != 0, mylist))
[1, None, 2, 1]  # missing False

>>> list(filter(lambda x: x != 0 and x is not type(int), mylist))
[1, None, 2, 1] # missing False

>>> list(filter(lambda x: x != 0 and x is not type(False), mylist))
[1, None, 2, 1]

>>> list(filter(lambda x: x != 0 and x is not False, mylist))
[1, None, 2, 1]
  

Желаемый результат:

 [1, None, 2, False, 1]
  

Спасибо за помощь.

Комментарии:

1. потому что False — это логическая версия 0

2. False равно 0 в Python. Это буквально целое число со значением 0. bool является int подклассом.

3. Да, я в курсе True True = 2 и True - False . Конечно, это просто логическое представление. Теперь я пришел сюда, чтобы спросить лучшее решение для случая выше.

Ответ №1:

Python bool является подклассом int и False аналогичен 0. Следовательно, сравнение по равенству не дает желаемого результата.

Вы можете использовать (обратите внимание, что это наименее предпочтительно, и в идеале вы не должны использовать):

 >>> list(filter(lambda x: x is not 0, mylist))
[1, None, 2, False, 1]
  

Что вы должны использовать:

Проверка подлинности может не сработать во всех случаях, как обсуждалось в комментариях. Более осуществимым способом было бы использовать проверку равенства с проверкой типа как:

 >>> list(filter(lambda x: x != 0 or isinstance(x, bool), mylist))
[1, None, 2, False, 1]
  

Лично я не поклонник filter and lambda , я бы использовал понимание списка, которое оказывается быстрее:

 >>> [x for x in mylist if x != 0 or isinstance(x, bool)]
[1, None, 2, False, 1]
  

Комментарии:

1. Этот код предполагает, что когда-либо будет только один 0 объект. Это предположение неверно. Например, на текущем CPython, и я полагаю, на любой 3.x версии CPython, pow(2, 128, 2**128) == 0 , но pow(2, 128, 2**128) is not 0 . Фильтрация списка с этим 0 в нем с помощью этого кода создает список, в котором все еще есть 0.

2. (2.x выдает те же результаты для этих сравнений, но на 2.x pow выдает 0L .)

3. Проверка подлинности 0 здесь в корне неверна. Проверка подлинности False или проверка типа int были бы более подходящими.

4. @user2357112, справедливое замечание, хотя я не думаю, что у OP есть случаи, когда мой первоначальный код терпит неудачу; но стоит отметить.

5. Не полагайтесь на детали реализации небольшого кэша int. Первое решение неверно

Ответ №2:

Вы также можете проверить тип данных x , а затем использовать != operator .

 # works for integer 0
[x for x in mylist if type(x) != int or x != 0] 
# works for float 0.0 as well
[x for x in mylist if (type(x) != int and type(x) != float) or x != 0]
  

Ответ №3:

type bool — это подтип int , поэтому False переводится 0 как . Я думаю, что решение состоит в том, чтобы упорядочить число и отфильтровать его. Здесь также приведены хорошие и лучшие ответы:

 list(filter(lambda x: str(x) != '0', mylist)) 
  

Ответ №4:

x is not 0 Подход работает, но, вероятно, не является оптимальным. Есть улучшения скорости за счет использования a list comprehension вместо использования вызовов to list() и to filter() .

Запустите это в записной книжке Jupyter и воспользуйтесь встроенной %timeit магией, чтобы увидеть, как быстро каждый из них может вернуть результат.

 mylist = [0, 1, None, 2, False, 1, 0]
  

Использование list() и filter()

 %timeit list(filter(lambda x: x is not 0, mylist))
**1.12 µs** ± 17.7 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
  

Использование понимания списка

 %timeit [i for i in mylist if i is not 0]
**411 ns** ± 8.42 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
  

Мы видим, что техника понимания списка работает значительно быстрее.

Комментарии:

1. Неправильно сравнивать целые числа по идентификатору, когда вы имеете в виду равенство