Come applicare un operatore logico a tutti gli elementi in un elenco Python


93

Ho un elenco di booleani in Python. Voglio AND (o OR o NOT) e ottenere il risultato. Il codice seguente funziona ma non è molto pitonico.

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

Qualche suggerimento su come renderlo più pitonico apprezzato.

Risposte:


181

Logico andin tutti gli elementi in a_list:

all(a_list)

Logico orin tutti gli elementi in a_list:

any(a_list)

Se ti senti creativo, puoi anche fare:

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)

tieni presente che quelli non vengono valutati in corto circuito, mentre i built-in lo sono ;-)

un altro modo divertente:

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

e ancora un altro:

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

e potremmo andare avanti tutto il giorno, ma sì, il modo pitonico è usare alle any:-)

A proposito, Python non ha l'eliminazione della ricorsione in coda, quindi non provare a tradurre direttamente il codice LISP ;-)


8
operator.and_ è l'operatore e bit per bit &, non l'operatore logico e.
Ants Aasma

1
fortunatamente True e False (come l'operazione desiderata) sono espressi rispettivamente a 1 e 0, quindi gli operatori bit per bit funzionano come logici ^ _ ^
fortran

6
Ha spiegato molte versioni ridondanti, ma non ha fornito la sintassi per la risposta corretta effettiva.
jwg

2
non sono d'accordo quello che vuoi, è nelle faq: stackoverflow.com/privileges/vote-down
fortran

2
Si noti che reduce()è disponibile functoolsda Python 3.0
Duncan WP

33

ANDing e ORing è 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

Annotare è anche abbastanza 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]

Naturalmente, il modo in cui usereste questi risultati potrebbe richiedere alcune interessanti applicazioni del teorema di DeMorgan.


4
Se vuoi mettere in cortocircuito la variante not, usa semplicemente le espressioni del generatore: all(not x for x in some_list)(ma è lo stesso di not any(some_list)(un'espressione abbastanza naturale, eh?)).
u0b34a0f6ae

16

Reduce può farlo:

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

Come ha detto Fortran, tutto è il modo più succinto per farlo. Ma riduci le risposte alla domanda più generale "Come applicare un operatore logico a tutti gli elementi in un elenco Python?"


4
ridurre non sta andando via, AFAIK. viene spostato nel modulo functools, dalla sua posizione precedente nello spazio dei nomi globale
Eli Bendersky,

1
@eliben: Perché parlare di Python 3 in futuro? ridurre è ancora lì . reduceè functools.reduce in Python 3
u0b34a0f6ae

Se rimuovi il , True, questa risposta sarà l'unica effettivamente equivalente al codice della domanda, per gli elenchi non booleani.
Thomas Ahle

10

L'idioma per tali operazioni è usare la reducefunzione (globale in Python 2.X, nel modulo functoolsin Python 3.X) con un operatore binario appropriato, preso dal operatormodulo o codificato esplicitamente. Nel tuo caso, lo èoperator.and_

reduce(operator.and_, [True, True, False])

4

Ecco un'altra soluzione:

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

def my_or(a_list):
    return True in a_list

L'istruzione AND di tutti gli elementi restituirà True se tutti gli elementi sono True, quindi nessun False in un elenco. L'operatore OR è simile, ma dovrebbe restituire True se almeno un valore True è presente in un elenco.


0

Come mostrano le altre risposte, esistono diversi modi per eseguire questa operazione. Ecco un'altra soluzione che utilizza le funzioni della libreria 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)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.