2015-08-24 14 views
20

Ho due liste booleani, ad esempio,Python E operatore su due liste booleane - come?

x=[True,True,False,False] 
y=[True,False,True,False] 

voglio E queste liste insieme, con i risultati attesi:

xy=[True,False,False,False] 

ho pensato che l'espressione x and y avrebbe funzionato, ma è venuto a scoprire che esso non: infatti, (x and y) != (y and x)

uscita di x and y: [True,False,True,False]

uscita di y and x: [True,True,False,False]

Usando di lista fa hanno uscita corretta. Meno male!

xy = [x[i] and y[i] for i in range(len(x)] 

Mente che non sono riuscito a trovare alcun riferimento che mi ha detto l'operatore avrebbe funzionato come ho cercato con xe y. Ma è facile provare cose in Python. Qualcuno può spiegarmi cosa sta succedendo con x and y?

E qui è un semplice programma di test:

import random 
random.seed() 
n = 10 
x = [random.random() > 0.5 for i in range(n)] 
y = [random.random() > 0.5 for i in range(n)] 
# Next two methods look sensible, but do not work 
a = x and y 
z = y and x 
# Next: apparently only the list comprehension method is correct 
xy = [x[i] and y[i] for i in range(n)] 
print 'x  : %s'%str(x) 
print 'y  : %s'%str(y) 
print 'x and y : %s'%str(a) 
print 'y and x : %s'%str(z) 
print '[x and y]: %s'%str(xy) 
+0

x è un elenco, y è un elenco. 'x e y' è vero se e solo se entrambe le liste non sono vuote (una lista vuota è 'false-y', tutte le liste non vuote sono 'truth-y'): cioè,' x e y' fa * non * 'e ogni elemento' o altrimenti si preoccupano dei valori. – user2864740

risposta

26

and restituisce semplicemente il primo o il secondo operando, in base al loro valore di verità. Se il primo operando è considerato falso, viene restituito, altrimenti viene restituito l'altro operando.

liste sono considerati vero quando non è vuoto, in modo che entrambi gli elenchi sono considerati veri. Il loro contenuto non ha un ruolo qui.

Poiché entrambi gli elenchi non sono vuoti, x and y restituisce semplicemente il secondo oggetto elenco; solo se x era vuoto sarebbe restituito invece:

>>> [True, False] and ['foo', 'bar'] 
['foo', 'bar'] 
>>> [] and ['foo', 'bar'] 
[] 

Vedi l'Truth value testing section nella documentazione Python:

Qualsiasi oggetto può essere testato per valore di verità, per l'uso in una condizione if o while o come operando delle operazioni booleane di seguito. I seguenti valori sono considerati falsi:

[...]

  • qualsiasi sequenza vuota, per esempio, '', (), [].

[...]

Tutti gli altri valori sono considerati veri - così oggetti di molti tipi sono sempre veri.

(sottolineatura mia), e il Boolean operations section destra sotto che:

x and y
se x è falso, quindi x, altrimenti y

Questo è un operatore di cortocircuito, quindi valuta solo il secondo argomento se il primo è True.

È infatti necessario testare i valori contenevano nelle liste in modo esplicito. Puoi farlo con una comprensione delle liste, come hai scoperto. È possibile riscrivere con la zip() function per accoppiare i valori:

[a and b for a, b in zip(x, y)] 
+1

grazie per la spiegazione eccellente e esp. ripetendo la cosa che avevo visto "se x è falso, poi x, altrimenti y", ma non completamente bocciato. Questo è un caso per RTFM e dovrei leggerlo con molta attenzione! –

2

Questo dovrebbe fare quello che vuoi:

xy = [a and b for a, b in zip(x, y)] 

La ragione x and y rendimenti y e y and x rendimenti x è perché gli operatori booleani in pitone restituire il ultimo valore controllato che determina la veridicità dell'espressione. Il valore non vuoto di list viene valutato a True e dal and richiede che entrambi gli operandi valutino True, l'ultimo operando controllato è il secondo operando. Contrasto con x or y, che restituirebbe x perché non è necessario controllare per determinare la veridicità dell'espressione.

0

È possibile utilizzare la funzione zip

x=[True,True,False,False] 
y=[True,False,True,False] 
z=[a and b for a,b in zip(x,y)] 
4

and non è necessariamente un operatore booleano; restituisce uno dei suoi due argomenti, indipendentemente dal loro tipo. Se il primo argomento è false-ish (False, zero numerico o una stringa/contenitore vuota), restituisce quell'argomento. Altrimenti, restituisce il secondo argomento.

Nel tuo caso, sia x e y sono liste non vuote, in modo che il primo argomento è sempre vero-ish, che significa x and y rendimenti y e y and x rendimenti x.

6

Si potrebbe utilizzare Numpy:

>>> import numpy as np 
>>> x=np.array([True,True,False,False]) 
>>> y=np.array([True,False,True,False]) 
>>> x & y 
array([ True, False, False, False], dtype=bool) 

Numpy consente operazioni numeriche e logiche su matrici quali:

>>> z=np.array([1,2,3,4]) 
>>> z+1 
array([2, 3, 4, 5]) 

È possibile eseguire bit e con l'operatore &.

Invece di una lista di comprensione, è possibile utilizzare NumPy per generare l'array booleano direttamente in questo modo:

>>> np.random.random(10)>.5 
array([ True, True, True, False, False, True, True, False, False, False], dtype=bool) 
0

Invece di usare

[a and b for a, b in zip(x, y)] 

uno potrebbe utilizzare la possibilità di numpy di moltiplicare valori bool:

(np.array(x)*np.array(y)) 
>> array([ True, False, False, False], dtype=bool) 

Oppure trascuro un caso speciale?

0

In aggiunta a ciò che @Martijn Pieters ha risposto, vorrei semplicemente aggiungere il seguente codice per spiegare le operazioni and e or in azione.

and restituisce il primo valore di falsy rilevato altro l'ultimo argomento valutato.

Analogamente or restituisce il primo valore di verità rilevato altro l'ultimo argomento valutato.

nl1 = [3,3,3,3,0,0,0,0] 
nl2 = [2,2,0,0,2,2,0,0] 
nl3 = [1,0,1,0,1,0,1,0] 
and_list = [a and b and c for a,b,c in zip(nl1,nl2,nl3)] 
or_list = [a or b or c for a,b,c in zip(nl1,nl2,nl3)] 

valori sono

and_list = [1, 0, 0, 0, 0, 0, 0, 0]

or_list = [3, 3, 3, 3, 2, 2, 1, 0]