So wenden Sie einen logischen Operator auf alle Elemente in einer Python-Liste an

87

Ich habe eine Liste von Booleschen Werten in Python. Ich möchte sie UND (oder ODER oder NICHT) und das Ergebnis erhalten. Der folgende Code funktioniert, ist aber nicht sehr pythonisch.

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

Vorschläge, wie man es pythonischer machen kann, werden geschätzt.

Robert Christie
quelle

Antworten:

171

Logisch andüber alle Elemente in a_list:

all(a_list)

Logisch orüber alle Elemente in a_list:

any(a_list)

Wenn Sie sich kreativ fühlen, können Sie auch Folgendes tun:

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)

Denken Sie daran, dass diese nicht im Kurzschluss ausgewertet werden, während die eingebauten sind ;-)

ein anderer lustiger Weg:

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

und noch eine:

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

und wir könnten den ganzen Tag weitermachen, aber ja, der pythonische Weg ist zu benutzen allund any:-)

Übrigens hat Python keine Eliminierung der Schwanzrekursion, also versuchen Sie nicht, LISP-Code direkt zu übersetzen ;-)

fortran
quelle
8
operator.and_ ist das bitweise und operator &, nicht das logische und.
Ants Aasma
1
Glücklicherweise werden True und False (wie gewünscht) auf 1 bzw. 0 gesetzt, sodass die bitweisen Operatoren als logische ^ _ ^
fortran
6
Erklärte viele redundante Versionen, lieferte jedoch nicht die Syntax für die tatsächlich richtige Antwort.
JWG
2
stimme nicht zu, was immer du willst, es steht in der FAQ: stackoverflow.com/privileges/vote-down
fortran
2
Beachten Sie, dass reduce()in functoolsPython 3.0
Duncan WP
33

ANDing und ORing ist einfach:

>>> 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 ist auch ziemlich einfach:

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

Wie Sie diese Ergebnisse verwenden würden, könnte natürlich einige interessante Anwendungen des DeMorgan-Theorems erfordern.

Jason Baker
quelle
4
Wenn Sie die nicht-Variante kurzschließen möchten, verwenden Sie einfach Generatorausdrücke: all(not x for x in some_list)(aber das ist dasselbe wie not any(some_list)(ein ganz natürlicher Ausdruck, oder?)).
u0b34a0f6ae
16

Reduzieren kann dies:

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

Wie fortran erwähnt hat, ist alles der prägnanteste Weg, dies zu tun. Reduzieren Sie jedoch die Antworten auf die allgemeinere Frage "Wie wende ich einen logischen Operator auf alle Elemente in einer Python-Liste an?"

Frank Krueger
quelle
4
reduzieren geht nicht weg, AFAIK. Es wird von seiner vorherigen Position im globalen Namespace
Eli Bendersky
1
@eliben: Warum über Python 3 in der Zukunftsform sprechen? reduzieren ist noch da . reduceist functools.reduce in Python 3
u0b34a0f6ae
Wenn Sie das entfernen , True, ist diese Antwort die einzige, die dem Code der Frage für nicht-boolesche Listen tatsächlich entspricht.
Thomas Ahle
10

Die Redewendung für solche Operationen besteht darin, die reduceFunktion (global in Python 2.X, im Modul functoolsin Python 3.X) mit einem geeigneten binären Operator zu verwenden, der entweder aus dem operatorModul stammt oder explizit codiert ist. In deinem Fall ist esoperator.and_

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

Hier ist eine andere Lösung:

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

def my_or(a_list):
    return True in a_list

Das ANDing aller Elemente gibt True zurück, wenn alle Elemente True sind, daher kein False in einer Liste. ORing ist ähnlich, sollte jedoch True zurückgeben, wenn mindestens ein True-Wert in einer Liste vorhanden ist.

Xarts
quelle
0

Wie die anderen Antworten zeigen, gibt es mehrere Möglichkeiten, diese Aufgabe zu erfüllen. Hier ist eine weitere Lösung, die Funktionen aus der Standardbibliothek verwendet:

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
quelle