Cómo aplicar un operador lógico a todos los elementos en una lista de Python

90

Tengo una lista de valores booleanos en Python. Quiero Y (o O o NO) y obtener el resultado. El siguiente código funciona pero no es muy pitónico.

def apply_and(alist):
 if len(alist) > 1:
     return alist[0] and apply_and(alist[1:])
 else:
     return alist[0]

Se agradece cualquier sugerencia sobre cómo hacerlo más pitónico.

Robert Christie
fuente

Respuestas:

176

Lógico anden todos los elementos en a_list:

all(a_list)

Lógico oren todos los elementos en a_list:

any(a_list)

Si se siente creativo, también puede hacer:

import operator
def my_all(a_list):
  return reduce(operator.and_, a_list, True)

def my_any(a_list):
  return reduce(operator.or_, a_list, False)

tenga en cuenta que esos no se evalúan en cortocircuito, mientras que los incorporados sí lo son ;-)

otra forma divertida:

def my_all_v2(a_list):
  return len(filter(None,a_list)) == len(a_list)

def my_any_v2(a_list):
  return len(filter(None,a_list)) > 0

y otro más:

def my_all_v3(a_list):
  for i in a_list:
    if not i:
      return False
  return True

def my_any_v3(a_list):
  for i in a_list:
    if i:
      return True
  return False

y podríamos seguir todo el día, pero sí, la forma pitónica es usar ally any:-)

Por cierto, Python no tiene eliminación de recursividad de cola, así que no intente traducir el código LISP directamente ;-)

fortran
fuente
8
operator.and_ es el operador and bit a bit y, no el and lógico.
Hormigas Aasma
1
afortunadamente, Verdadero y Falso (como quería la operación) se convierten en 1 y 0 respectivamente, por lo que los operadores bit a bit funcionan como el ^ _ ^ lógico
fortran
6
Explicó muchas versiones redundantes, pero no proporcionó la sintaxis de la respuesta correcta real.
jwg
2
no está de acuerdo con lo que quiera, está en las preguntas frecuentes
fortran
2
Tenga reduce()en cuenta que está disponible functoolsdesde Python 3.0
Duncan WP
33

Hacer AND y OR es fácil:

>>> some_list = [True] * 100
# OR
>>> any(some_list)
True
#AND
>>> all(some_list)
True
>>> some_list[0] = False
>>> any(some_list)
True
>>> all(some_list)
False

NOTAR también es bastante fácil:

>>> [not x for x in some_list]
[True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]

Por supuesto, la forma en que usaría esos resultados podría requerir algunas aplicaciones interesantes del teorema de DeMorgan.

Jason Baker
fuente
4
Si desea un cortocircuito de la variante not, simplemente use expresiones generadoras: all(not x for x in some_list)(pero eso es lo mismo que not any(some_list)(una expresión bastante natural, ¿eh?)).
u0b34a0f6ae
16

Reducir puede hacer esto:

reduce(lambda a,b: a and b, alist, True)

Como mencionó fortran, todo es la forma más sucinta de hacerlo. Pero reduzca las respuestas a la pregunta más general "¿Cómo aplicar un operador lógico a todos los elementos en una lista de Python?"

Frank Krueger
fuente
4
reducir no va a desaparecer, AFAIK. se está moviendo al módulo de funciones, desde su posición anterior en el espacio de nombres global
Eli Bendersky
1
@eliben: ¿Por qué hablar de Python 3 en tiempo futuro? reducir todavía está ahí . reduceestá functools.reduce en Python 3
u0b34a0f6ae
Si elimina , True, esta respuesta será la única realmente equivalente al código de la pregunta, para listas no booleanas.
Thomas Ahle
10

El lenguaje para tales operaciones es usar la reducefunción (global en Python 2.X, en el módulo functoolsen Python 3.X) con un operador binario apropiado, ya sea tomado del operatormódulo o codificado explícitamente. En tu caso, esoperator.and_

reduce(operator.and_, [True, True, False])
Eli Bendersky
fuente
4

Aquí hay otra solución:

def my_and(a_list):
    return not (False in a_list)

def my_or(a_list):
    return True in a_list

La operación AND de todos los elementos devolverá True si todos los elementos son True, por lo tanto, no False en una lista. La operación OR es similar, pero debería devolver True si al menos un valor True está presente en una lista.

Xarts
fuente
0

Como muestran las otras respuestas, hay varias formas de realizar esta tarea. Aquí hay otra solución que usa funciones de la biblioteca estándar:

from functools import partial

apply_and = all
apply_or = any
apply_not = partial(map, lambda x: not x)

if __name__ == "__main__":
    ls = [True, True, False, True, False, True]
    print "Original: ", ls
    print "and: ", apply_and(ls)
    print "or: ", apply_or(ls)
    print "not: ", apply_not(ls)
mipadi
fuente