Comment appliquer un opérateur logique à tous les éléments d'une liste Python

90

J'ai une liste de booléens en python. Je veux les ET (ou OU ou PAS) et obtenir le résultat. Le code suivant fonctionne mais n'est pas très pythonique.

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

Toutes les suggestions sur la façon de le rendre plus pythonique appréciées.

Robert Christie
la source

Réponses:

176

Logique à andtravers tous les éléments dans a_list:

all(a_list)

Logique à ortravers tous les éléments dans a_list:

any(a_list)

Si vous vous sentez créatif, vous pouvez également faire:

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)

gardez à l'esprit que ceux-ci ne sont pas évalués en court-circuit, tandis que les intégrés le sont ;-)

une autre façon amusante:

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

et encore un autre:

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

et nous pourrions continuer toute la journée, mais oui, la manière pythonique est d'utiliser allet any:-)

Au fait, Python n'a pas d'élimination de la récursivité, alors n'essayez pas de traduire directement le code LISP ;-)

fortran
la source
8
operator.and_ est l'opérateur et au niveau du bit et non le et logique.
Ants Aasma
1
Heureusement, True et False (comme l'op a voulu) sont convertis respectivement en 1 et 0, donc les opérateurs au niveau du bit fonctionnent comme la logique ^ _ ^
fortran
6
Expliqué de nombreuses versions redondantes, mais n'a pas fourni la syntaxe de la réponse correcte.
jwg
2
pas d'accord ce que vous voulez, c'est dans la FAQ: stackoverflow.com/privileges/vote-down
fortran
2
Notez que reduce()c'est functoolsdepuis Python 3.0
Duncan WP
33

ANDing et ORing est facile:

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

NOTing est également assez facile:

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

Bien sûr, la façon dont vous utiliseriez ces résultats pourrait nécessiter des applications intéressantes du théorème de DeMorgan.

Jason Baker
la source
4
Si vous voulez une courte diffusion de la variante not, utilisez simplement des expressions génératrices: all(not x for x in some_list)(mais c'est la même chose que not any(some_list)(une expression assez naturelle, hein?)).
u0b34a0f6ae
16

Réduire peut faire ceci:

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

Comme l'a mentionné fortran, tout est la manière la plus succincte de le faire. Mais réduisez les réponses à la question plus générale "Comment appliquer un opérateur logique à tous les éléments d'une liste python?"

Frank Krueger
la source
4
réduire ne va pas loin, AFAIK. il est déplacé dans le module functools, depuis sa position précédente dans l'espace de noms global
Eli Bendersky
1
@eliben: Pourquoi parler de Python 3 au futur? réduire est toujours là .reduceest functools.reduce en Python 3
u0b34a0f6ae
Si vous supprimez le , True, cette réponse sera la seule réellement équivalente au code de la question, pour les listes non booléennes.
Thomas Ahle
10

L'idiome pour de telles opérations est d'utiliser la reducefonction (globale en Python 2.X, en module functoolsen Python 3.X) avec un opérateur binaire approprié, soit pris dans le operatormodule, soit codé explicitement. Dans votre cas, c'estoperator.and_

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

Voici une autre solution:

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

def my_or(a_list):
    return True in a_list

ANDing tous les éléments renverra True si tous les éléments sont True, donc aucun False dans une liste. ORing est similaire, mais il doit renvoyer True si au moins une valeur True est présente dans une liste.

Xarts
la source
0

Comme le montrent les autres réponses, il existe plusieurs façons d'accomplir cette tâche. Voici une autre solution qui utilise des fonctions de la bibliothèque standard:

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