values true problems lists from are all python list count boolean

python - true - ¿Cuándo debo usar list.count(0) y cómo puedo descontar el artículo "Falso"?



python all in list are true (9)

a.count(0) siempre devuelve 11, entonces, ¿qué debo hacer para descontar lo False y devolver 10?

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


¿Qué hay de esta solución de estilo funcional:

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

Al comparar esto con algunas de las otras respuestas aquí, esto también parece ser uno de los más rápidos:

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


Dado que el count devuelve el número de elementos igual a su entrada, y como 0 es igual a False en Python, una forma de aproximarse a esto es pasar algo que sea igual a 0 pero no sea igual a False .

Python en sí no proporciona tal objeto, pero podemos escribir uno:

class Zero: def __eq__(self, other): return other == 0 and other is not False print([1, 2, 0, False].count(Zero()))

Tenga en cuenta que hay otras cosas en Python que, como False , son iguales a 0 . Puedo pensar en 0.0 , decimal.Decimal(0) y fractions.Fraction(0,1) . Además, cualquiera puede subclasificar int para crear otros "valores 0 falsos", como False . El código anterior cuenta todos estos factores, tratando a False como el único caso especial, pero es posible que desee hacer algo diferente en su __eq__ .

Por supuesto, "debajo de las portadas" es muy similar a solo hacer sum(other == 0 and other is not False for other in a) . Pero considerando cómo se define count() , no debería sorprender que a.count(x) sea ​​similar a la sum(x == y for y in a) .

Solo haría esto en el caso poco frecuente de que, por algún motivo, ya haya decidido usar el count (tal vez porque está usando un código de terceros que lo va a llamar), y necesita encontrar un objeto adecuado para pasar. eso. Básicamente, trata la count como una función que llama a una función arbitraria que escribimos (que solo requiere que esta función sea la función __eq__ del argumento) y cuenta el número de valores de retorno verdaderos. Esta es una descripción precisa de lo que hace el count , pero no es realmente el punto de count ya que la sum es más explícita.


Muchas respuestas apropiadas ya dadas. Por supuesto, una alternativa es filtrar la lista según el tipo de elemento que está buscando primero.

>>> 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

En caso de que esté preocupado por la copia, puede usar la sum y abusar del hecho que intentamos evadir arriba (eso es True == 1 ).

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


Necesitas filtrar los Falses tú mismo.

>>> 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

La respuesta anterior es específica de CPython y es mejor usar soluciones que funcionen en todas las implementaciones de Python.

Como CPython mantiene un grupo de pequeños objetos enteros , cero incluido, puede filtrar la lista con el operador is .

Por supuesto, esto no debería usarse para comparaciones de valores, pero en este caso funciona porque los ceros son lo que queremos encontrar.

>>> 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


Otra opción es primero "decorar" la lista agregando los tipos y el conteo:

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

Si quieres tener 0 == 0.0 podrías hacer:

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

Lo que cuenta todos los 0 s que no son de tipo bool (es decir, False s). De esta manera, puede definir qué debe hacer el count forma que desee, al costo de crear una lista temporal.


Podrías usar sum y una expresión generadora:

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


Python 2.x interpreta False como 0 y viceversa. AFAIK incluso None y "" puede considerarse False en las condiciones. Redefinir el recuento de la siguiente manera:

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

o (Gracias a Kevin , y Bakuriu por sus comentarios):

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

o según lo sugerido por ozgur en los comentarios (lo cual no se recomienda y se considera incorrecto , vea Kevin ), simplemente:

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

puede que (el operador "es" se comporte inesperadamente con enteros ) funcione para tipos primarios pequeños , pero si su lista contiene objetos, tenga en cuenta lo que hace el operador:

De la documentación para el operador is :

Los operadores is y is not prueban la identidad del objeto: x is y es verdadero si y solo si x e y son el mismo objeto.

Más información sobre el operador is : Entendiendo el operador "is" de Python


Si resuelve este problema de manera más general, puede crear su propia subclase de lista:

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)

Y luego define una función clave que verifica los tipos:

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

Entonces tu uso se convierte en:

>>> 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


Si se encuentra con este tipo de problemas con frecuencia, puede introducir la siguiente clase *

class Exactly: def __init__(self, something): self.value = something def __eq__(self, other): return type(self.value) == type(other) and self.value == other

y usarlo de la siguiente manera:

a.count(Exactly(0))

* Por supuesto, es posible que también necesite mejorarlo para otras operaciones.