Подтвердить что ты не робот

Когда следует использовать list.count(0) и как мне сбрасывать товар "False"?

a.count(0) всегда возвращает 11, поэтому что мне делать, чтобы скинуть False и вернуть 10?

a = ["a",0,0,"b",None,"c","d",0,1,False,0,1,0,3,[],0,1,9,0,0,{},0,0,9]
4b9b3361

Ответ 1

Python 2.x интерпретирует False как 0 и наоборот. AFAIK даже None и "" можно считать False в условиях. Переопределить счет следующим образом:

sum(1 for item in a if item == 0 and type(item) == int)

или (спасибо Кевин и Bakuriu за свои комментарии):

sum(1 for item in a if item == 0 and type(item) is type(0))

или как предложено ozgur в комментариях (, который не рекомендуется и считается неправильным, см. this), просто:

sum(1 for item in a if item is 0)  

он может ( "является" оператор ведет себя неожиданно с целыми числами) работает для небольших первичных типов, но если ваш список содержит объекты, пожалуйста, рассмотрим, что делает оператор is:

Из документации для оператора is:

Операторы is и is not проверяют идентичность объекта: x is y истинно тогда и только тогда, когда x и y являются одним и тем же объектом.

Дополнительная информация о операторе is: Понимание Python "is" operator

Ответ 2

Это можно сделать с помощью sum и выражения-генератора, которое сравнивает каждый элемент с False:

>>> a = ["a",0,0,"b",None,"c","d",0,1,False,0,1,0,3,[],0,1,9,0,0,{},0,0,9]
>>> sum((x == 0 and x is not False) for x in a)
10

Это работает, потому что bool является подклассом int - False равно 0 и True равно 1.

Ответ 3

Вам нужно отфильтровать Falses самостоятельно.

>>> a = ["a",0,0,"b",None,"c","d",0,1,False,0,1,0,3,[],0,1,9,0,0,{},0,0,9]
>>> len([x for x in a if x == 0 and x is not False])
10

Старый ответ специфичен для CPython, и лучше использовать решения, которые работают на всех реализациях Python.

Так как CPython хранит пул небольших целых объектов, нуль включен, вы можете отфильтровать список с помощью оператора is.

Это, конечно, не следует использовать для сравнения значений, но в этом случае оно работает, так как нули - это то, что мы хотим найти.

>>> a = ["a",0,0,"b",None,"c","d",0,1,False,0,1,0,3,[],0,1,9,0,0,{},0,0,9]
>>> [x for x in a if x is 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
>>> len(_)
10

Ответ 4

Как об этом решении функционального стиля:

print zip(a, map(type, a)).count((0, int))
>>> 10

Считая это против некоторых других ответов здесь, это также кажется одним из самых быстрых:

t0 = time.time()
for i in range(100000):
    zip(a, map(type, a)).count((0, int))
print time.time() - t0
>>> 0.275855064392

t0 = time.time()
for i in range(100000):
    sum(1 for item in a if item == 0 and type(item) == int)
print time.time() - t0
>>> 0.478030204773

t0 = time.time()
for i in range(100000):
    sum(1 for item in a if item == 0 and type(item) is type(0))
print time.time() - t0
>>> 0.52236700058

t0 = time.time()
for i in range(100000):
    sum((x==0 and x is not False) for x in a)
print time.time() - t0
>>> 0.450266122818

Ответ 5

Решая эту проблему в более общем плане, вы можете создать свой собственный подкласс списка:

class key_equality_list(list):
    def __init__(self, key, items):
        super(key_equality_list, self).__init__(items)
        self._f = key

    def __contains__(self, x):
        return any(self._f(x) == self._f(item) for item in self)

    def count(self, x):
        return sum(self._f(x) == self._f(item) for item in self)

И затем определите ключевую функцию, которая проверяет типы:

type_and_val = lambda x: (x, type(x))

Итак, ваше использование будет:

>>> a = ["a",0,0,"b",None,"c","d",0,1,False,0,1,0,3,[],0,1,9,0,0,{},0,0,9]
>>> a = key_equality_list(type_and_val, a)
>>> a.count(0)
10
>>> a.count(False)
1

Ответ 6

Другой вариант - сначала "украсить" список, добавив типы и счетчик:

decorated_seq = list(map(lambda x: (x, type(x)), sequence))
decorated_seq.count((0, type(0)))

Если вы хотите иметь 0 == 0.0, вы можете сделать:

decorated_seq = list(map(lambda x: (x, isinstance(x, bool)), sequence))
decorated_seq.count((0, False))

Что подсчитывает все 0, которые не относятся к типу bool (т.е. False s). Таким образом, вы можете определить, что count должно делать так, как вам угодно, за счет создания временного списка.

Ответ 7

Так как count возвращает количество элементов, равное его вводу, а так как 0 равно False в Python, один из способов приблизиться к этому - передать что-то, равное 0, но не равным False.

Сам Python не предоставляет такого объекта, но мы можем написать его:

class Zero:
    def __eq__(self, other):
        return other == 0 and other is not False

print([1, 2, 0, False].count(Zero()))

Помните, что в Python есть другие вещи, которые, как и False, равны 0. Я могу думать о 0.0, decimal.Decimal(0) и fractions.Fraction(0,1). Кроме того, любой может подклассифицировать int для создания других "поддельных значений 0", как и False. В приведенном выше коде учитывается все из них, рассматривая False как единственный частный случай, но вы можете сделать что-то другое в своем __eq__.

Конечно, "под обложками" это очень похоже на простое выполнение sum(other == 0 and other is not False for other in a). Но, учитывая, как count() определен, неудивительно, что a.count(x) похож на sum(x == y for y in a).

Вы сделали бы это только в редком случае, когда по какой-то причине вы решили использовать count (возможно, потому, что вы используете какой-то сторонний код, который будет его называть), и вам нужно придумать подходящий объект для его прохождения. В основном, он рассматривает count как функцию, которая вызывает произвольную функцию, которую мы пишем (требуя только, чтобы эта функция была функцией __eq__ аргумента) и подсчитывала количество истинных возвращаемых значений. Это точное описание того, что делает count, но не действительно точка count, поскольку sum является более явным.

Ответ 8

Многие соответствующие ответы уже даны. Конечно, альтернативой является фильтрация списка по типу элемента, который вы запрашиваете для первого.

>>> a = ["a",0,0,"b",None,"c","d",0,1,False,0,1,0,3,[],0,1,9,0,0,{},0,0,9]
>>> def count(li, item):
...     return list(filter(lambda x: type(x) == type(item), li)).count(item)
...
>>>
>>> count(a, 0)
10
>>> count(a, False)
1
>>> count(a, "a")
1
>>> class my_own_int(int): pass
...
>>> a.append(my_own_int(5))
>>> a.count(5)
1
>>> count(a, 5)
0

Если вас беспокоит копия, вы можете использовать sum и злоупотреблять тем, что мы пытаемся обойти выше (это True == 1).

def count(li, item):
    return sum(map(lambda x: x == item, filter(lambda x: type(x) == type(item), li))) 

Ответ 9

Если вы часто сталкиваетесь с такими проблемами, вы можете ввести следующий класс *

class Exactly:
    def __init__(self, something):
        self.value = something

    def __eq__(self, other):
        return type(self.value) == type(other) and self.value == other

и используйте его следующим образом:

a.count(Exactly(0)) 

* Конечно, вам может потребоваться усилить его и для других операций.