#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. Неправильно сравнивать целые числа по идентификатору, когда вы имеете в виду равенство