web-dev-qa-db-fra.com

Opération logique entre deux listes booléennes

J'obtiens un résultat bizarre et j'essaie d'appliquer l'opérateur and ou or à 2 listes booléennes en python. J'obtiens en fait exactement le contraire de ce que j'attendais.

[True, False, False] and [True, True, False]
> [True, True, False]

[True, False, False] or [True, True, False]
> [True, False, False]

Est-ce normal, et si oui, pourquoi?

11
Yohan Obadia

Vos listes ne comparent pas chaque valeur individuelle, elles comparent l'existence de valeurs dans la liste.

Pour toutes les variables véridiques a et b:

a and b
> b #The program evaluates a, a is truthy, it evaluates b, b is truthy, so it returns the last evaluated value, b.
a or b
> a #The program evaluates a, a is truthy, so the or statement is true, so it returns the last evaluated value, a.

Maintenant, la vérité dépend du type. Par exemple, les entiers sont vrais pour my_int != 0, et sont fausses pour my_int == 0. Donc si vous avez:

a = 0
b = 1
a or b
> b #The program evaluates a, a is falsy, so the or statement goes on to evaluate b, b is truthy, so the or statement is true and it returns the last evaluated value b.
3
Davy M

Si vous vouliez réellement des opérations booléennes par élément entre vos deux listes, envisagez d'utiliser le module numpy:

>>> import numpy as np
>>> a = np.array([True, False, False])
>>> b = np.array([True, True, False])
>>> a & b
array([ True, False, False], dtype=bool)
>>> a | b
array([ True,  True, False], dtype=bool)
10
jasonharper

C'est normal, car and et or évaluent en fait l'un de leurs opérandes. x and y est comme

def and(x, y):
    if x:
        return y
    return x

tandis que x or y est comme

def or(x, y):
    if x:
        return x
    return y

Étant donné que vos deux listes contiennent des valeurs, elles sont toutes les deux "truey" donc and évalue le deuxième opérande et or évalue le premier.

5
Patrick Haugh

Je pense que vous avez besoin de quelque chose comme ça:

[x and y for x, y in Zip([True, False, False], [True, True, False])]
3
AyumuKasuga

Les deux listes sont véridiques car elles ne sont pas vides.

and et or renvoient l'opérande qui a décidé de la valeur de l'opération.

Si le côté gauche de and est véridique, il doit évaluer le côté droit, car il pourrait être faux, ce qui rendrait toute l'opération fausse (false and tout est faux). Par conséquent, il renvoie le côté droit.

Si le côté gauche de or est véridique, il n'a pas besoin d'évaluer le côté droit, car il sait déjà que l'expression est vraie (true or tout est vrai). Il renvoie donc le côté gauche.

Si vous souhaitez effectuer des comparaisons par paire des éléments de la liste, utilisez une compréhension de la liste, par exemple:

[x or y for (x, y) in Zip(a, b)]     # a and b are your lists
3
kindall

Manière très pratique:

>>> import numpy as np
>>> np.logical_and([True, False, False], [True, True, False])
array([ True, False, False], dtype=bool)
>>> np.logical_or([True, False, False], [True, True, False])
array([ True,  True, False], dtype=bool)
1
Markus Dutschke

Plus fonctionnel:

from operator import or_, and_
from itertools import starmap

a = [True, False, False]
b = [True, True, False]
starmap(or_, Zip(a,b))  # [True, True, False]
starmap(and_, Zip(a,b))  # [True, False, False]
1
Lecron