web-dev-qa-db-fra.com

Comment tester plusieurs variables par rapport à une valeur?

J'essaie de créer une fonction qui compare plusieurs variables à un entier et génère une chaîne de trois lettres. Je me demandais s'il y avait un moyen de traduire cela en Python. Dites donc:

x = 0
y = 1
z = 3
mylist = []

if x or y or z == 0 :
    mylist.append("c")
if x or y or z == 1 :
    mylist.append("d")
if x or y or z == 2 :
    mylist.append("e")
if x or y or z == 3 : 
    mylist.append("f")

qui renverrait une liste de 

["c", "d", "f"]

Est-ce que quelque chose comme ça est possible?

494
user1877442

Vous comprenez mal le fonctionnement des expressions booléennes; ils ne fonctionnent pas comme une phrase anglaise et supposez que vous parlez de la même comparaison pour tous les noms ici. Tu recherches:

if x == 1 or y == 1 or z == 1:

x et y sont par ailleurs évalués séparément (False si 0, True sinon).

Vous pouvez raccourcir cela en utilisant un test de confinement contre un tuple :

if 1 in (x, y, z):

ou mieux encore:

if 1 in {x, y, z}:

utiliser a set pour tirer parti du test d’appartenance à coût constant (in prend un temps fixe, quelle que soit l’opérande de gauche).

Lorsque vous utilisez or, python voit chaque côté de l'opérateur sous forme d'expressions Separate. L'expression x or y == 1 est traitée en premier lieu comme un test booléen pour x. Si c'est faux, l'expression y == 1 est testée.

Cela est dû à priorité des opérateurs . L'opérateur or a une priorité inférieure à celle du test ==, de sorte que ce dernier est évalué premier.

Cependant, même si c'était le cas not et si l'expression x or y or z == 1 était en fait interprétée comme étant (x or y or z) == 1, cela ne ferait toujours pas ce que vous espériez. 

x or y or z évalue le premier argument qui est 'vérité', par exemple. pas False, numérique 0 ou vide (voir expressions booléennes pour plus de détails sur ce que Python considère comme faux dans un contexte booléen).

Ainsi, pour les valeurs x = 2; y = 1; z = 0, x or y or z serait résolu en 2, car il s'agit de la première valeur de type true dans les arguments. Alors 2 == 1 serait False, même si y == 1 serait True.

La même chose s'appliquerait à l'inverse; tester plusieurs valeurs par rapport à une seule variable; x == 1 or 2 or 3 échouerait pour les mêmes raisons. Utilisez x == 1 or x == 2 or x == 3 ou x in {1, 2, 3}.

669
Martijn Pieters

Votre problème est plus facilement résolu avec une structure de dictionnaire comme:

x = 0
y = 1
z = 3
d = {0: 'c', 1:'d', 2:'e', 3:'f'}
mylist = [d[k] for k in [x, y, z]]
78
dansalmo

Solution précédente: Comme l'a déclaré Martijn Pieters, le format correct et le plus rapide est:

if 1 in {x, y, z}:

Le problème majeur qui semble ne pas être résolu est que vous souhaitez que votre liste de résultats inclue chaque lettre après une instruction true. 

En utilisant uniquement les conseils de Martijn Pieters, vous auriez maintenant:

if 0 in {x, y, z}:
    Mylist.append("c")
Elif 1 in {x, y, z}:
    Mylist.append("d")
...

Problème: La première instruction if retournerait true et vous n'obtiendriez jamais l'instruction Elif suivante. Donc, votre liste renverrait simplement:

["c"]

Ce que vous voulez, c'est avoir des instructions if distinctes afin que python lise chaque instruction, que celle-ci soit vraie ou fausse. Tel que:

if 0 in {x, y, z}:
    Mylist.append("c")
if 1 in {x, y, z}:
    Mylist.append("d")
if 2 in {x, y, z}:
    Mylist.append("e")
...

Cela fonctionnera, mais 'si' vous êtes à l'aise avec les dictionnaires (voyez ce que j'ai fait ici), vous pouvez le nettoyer en créant un dictionnaire initial mappant les nombres sur les lettres souhaitées, puis en utilisant simplement une boucle 'pour':

numToLetters = {0:"c", 1:"d", 2:"e", 3:"f"}
for number in numToLetters:
    if number in {x, y, z}:
        Mylist.append(numToLetters[number])
51
ThatGuyRussell

Le moyen direct pour écrire x or y or z == 0 est

if any(map((lambda value: value == 0), (x,y,z))):
    pass # write your logic.

Mais je ne pense pas que ça vous plaise. :) Et cette façon est laide.

L'autre façon (un meilleur) est:

0 in (x, y, z)

BTW beaucoup de ifs pourraient être écrits comme ceci

my_cases = {
    0: Mylist.append("c"),
    1: Mylist.append("d")
    # ..
}

for key in my_cases:
    if key in (x,y,z):
        my_cases[key]()
        break
36
akaRem

Si vous êtes très très paresseux, vous pouvez mettre les valeurs dans un tableau. Tel que

list = []
list.append(x)
list.append(y)
list.append(z)
nums = [add numbers here]
letters = [add corresponding letters here]
for index in range(len(nums)):
    for obj in list:
        if obj == num[index]:
            MyList.append(letters[index])
            break

Vous pouvez également mettre les chiffres et les lettres dans un dictionnaire et le faire, mais c'est probablement beaucoup plus compliqué que de simples déclarations. C'est ce que vous obtenez pour essayer d'être très paresseux :)

Une dernière chose, votre 

if x or y or z == 0:

compilera, mais pas comme vous le souhaitez. Lorsque vous mettez simplement une variable dans une instruction if (exemple)

if b

le programme vérifiera si la variable n'est pas nulle. Une autre façon d’écrire la déclaration ci-dessus (ce qui a plus de sens) est 

if bool(b)

Bool est une fonction intégrée à python qui vérifie essentiellement une déclaration booléenne (si vous ne savez pas ce que c'est, c'est ce que vous essayez de faire dans votre déclaration if maintenant :))

Une autre manière paresseuse que j'ai trouvée est:

if any([x==0, y==0, z==0])
26
ytpillai

Pour vérifier si une valeur est contenue dans un ensemble de variables, vous pouvez utiliser les modules intégrés itertools et operator.

Par exemple:

Importations:

from itertools import repeat
from operator import contains

Déclarer des variables:

x = 0
y = 1
z = 3

Créez un mappage de valeurs (dans l'ordre que vous souhaitez vérifier):

check_values = (0, 1, 3)

Utilisez itertools pour autoriser la répétition des variables:

check_vars = repeat((x, y, z))

Enfin, utilisez la fonction map pour créer un itérateur:

checker = map(contains, check_vars, check_values)

Ensuite, lors de la vérification des valeurs (dans l'ordre d'origine), utilisez next():

if next(checker)  # Checks for 0
    # Do something
    pass
Elif next(checker)  # Checks for 1
    # Do something
    pass

etc...

Cela présente un avantage par rapport à lambda x: x in (variables) car operator est un module intégré, plus rapide et plus efficace que d'utiliser lambda qui doit créer une fonction in-situ personnalisée.

Une autre option pour vérifier s'il existe une valeur non nulle (ou Faux) dans une liste:

not (x and y and z)

Équivalent:

not all((x, y, z))
24
GuiltyDolphin

Toutes les excellentes réponses fournies ici se concentrent sur les exigences spécifiques de l’affiche originale et sur la solution if 1 in {x,y,z} proposée par Martijn Pieters.
Ce qu’ils ignorent, c’est l’implication plus large de la question:
Comment tester une variable contre plusieurs valeurs?
La solution fournie ne fonctionnera pas pour les hits partiels si vous utilisez des chaînes par exemple:
Teste si la chaîne "Wild" est dans plusieurs valeurs

>>> x = "Wild things"
>>> y = "throttle it back"
>>> z = "in the beginning"
>>> if "Wild" in {x, y, z}: print (True)
... 

ou

>>> x = "Wild things"
>>> y = "throttle it back"
>>> z = "in the beginning"
>>> if "Wild" in [x, y, z]: print (True)
... 

pour ce scénario, il est plus facile de convertir en chaîne

>>> [x, y, z]
['Wild things', 'throttle it back', 'in the beginning']
>>> {x, y, z}
{'in the beginning', 'throttle it back', 'Wild things'}
>>> 

>>> if "Wild" in str([x, y, z]): print (True)
... 
True
>>> if "Wild" in str({x, y, z}): print (True)
... 
True

Comme indiqué par @codeforester, il est à noter que les limites de Word sont perdues avec cette méthode, comme dans: 

>>> x=['Wild things', 'throttle it back', 'in the beginning']
>>> if "rot" in str(x): print(True)
... 
True

les 3 lettres rot existent en combinaison dans la liste mais pas en tant que mot individuel. Le test de "pourriture" échouerait, mais si l'un des éléments de la liste était "pourrir en enfer", cela échouerait également.
En fin de compte, soyez prudent avec vos critères de recherche si vous utilisez cette méthode et sachez qu’il a cette limitation.

22
Rolf of Saxony

Si vous voulez utiliser if, else, voici une autre solution:

myList = []
aList = [0, 1, 3]

for l in aList:
    if l==0: myList.append('c')
    Elif l==1: myList.append('d')
    Elif l==2: myList.append('e')
    Elif l==3: myList.append('f')

print(myList)
22
paarsa

Je pense que cela va mieux le gérer:

my_dict = {0: "c", 1: "d", 2: "e", 3: "f"}

def validate(x, y, z):
    for ele in [x, y, z]:
        if ele in my_dict.keys():
            return my_dict[ele]

Sortie:

print validate(0, 8, 9)
c
print validate(9, 8, 9)
None
print validate(9, 8, 2)
e
22
Bhargav Boda

Set est la bonne approche ici, car elle ordonne les variables, ce qui semble être votre objectif ici. {z,y,x} est {0,1,3} quel que soit l'ordre des paramètres.

>>> ["cdef"[i] for i in {z,x,y}]
['c', 'd', 'f']

De cette façon, la solution entière est O (n).

22
B. M.

Ce code peut être utile

L ={x, y, z}
T= ((0,"c"),(1,"d"),(2,"e"),(3,"f"),)
List2=[]
for t in T :
if t[0] in L :
    List2.append(t[1])
    break;
19
michael zxc858
d = {0:'c', 1:'d', 2:'e', 3: 'f'}
x, y, z = (0, 1, 3)
print [v for (k,v) in d.items() if x==k or y==k or z==k]
19
Saksham Varma

Une solution en ligne:

mylist = [{0: 'c', 1: 'd', 2: 'e', 3: 'f'}[i] for i in [0, 1, 2, 3] if i in (x, y, z)]

Ou:

mylist = ['cdef'[i] for i in range(4) if i in (x, y, z)]
5

Vous pouvez essayer la méthode ci-dessous. Dans cette méthode, vous aurez la liberté de spécifier/entrer le nombre de variables que vous souhaitez entrer.

mydict = {0:"c", 1:"d", 2:"e", 3:"f"}
mylist= []

num_var = int(raw_input("How many variables? ")) #Enter 3 when asked for input.

for i in range(num_var): 
    ''' Enter 0 as first input, 1 as second input and 3 as third input.'''
    globals()['var'+str('i').zfill(3)] = int(raw_input("Enter an integer between 0 and 3 "))
    mylist += mydict[globals()['var'+str('i').zfill(3)]]

print mylist
>>> ['c', 'd', 'f']
3
Siddharth Satpathy

Cela vous aidera.

def test_fun(val):
    x = 0
    y = 1
    z = 2
    myList = []
    if val in (x, y, z) and val == 0:
        myList.append("C")
    if val in (x, y, z) and val == 1:
        myList.append("D")
    if val in (x, y, z) and val == 2:
        myList.append("E")

test_fun(2);
3
Mayur

Cela peut se faire facilement 

for value in [var1,var2,var3]:
     li.append("targetValue")
2
Seenivasan

On dirait que vous construisez une sorte de chiffre de César.

Une approche beaucoup plus générale est la suivante:

input_values = (0, 1, 3)
origo = ord('c')
[chr(val + origo) for val in inputs]

les sorties

['c', 'd', 'f']

Pas sûr que ce soit un effet secondaire souhaité de votre code, mais l'ordre de votre sortie sera toujours trié.

Si c'est ce que vous voulez, la dernière ligne peut être changée en:

sorted([chr(val + origo) for val in inputs])
1
firelynx

Pour tester plusieurs variables avec une seule valeur: if 1 in {a,b,c}:

Pour tester plusieurs valeurs avec une variable: if a in {1, 2, 3}:

1
Md. Alamin Mahamud

La manière la plus mnémonique de représenter votre pseudo-code en Python serait:

x = 0
y = 1
z = 3
mylist = []

if any(v == 0 for v in (x, y, z)):
    mylist.append("c")
if any(v == 1 for v in (x, y, z)):
    mylist.append("d")
if any(v == 2 for v in (x, y, z)):
    mylist.append("e")
if any(v == 3 for v in (x, y, z)):
    mylist.append("f")
1
rsalmei

Peut-être avez-vous besoin d'une formule directe pour le jeu de bits de sortie.

x = 0 ou y = 0 ou z = 0 est équivalent à xy z = 0

x = 1 ou y = 1 ou z = 1 est équivalent à (x-1) (y-1) (z-1) = 0

x = 2 ou y = 2 ou z = 2 est équivalent à (x-2) (y-2) (z-2) = 0

permet de mapper sur les bits: 'c': 1 'd': 0xb10 'e': 0xb100 'f': 0xb1000

relation de isc:

si xyz = 0 alors isc = 1 sinon isc = 0

utilisez math si formula https://youtu.be/KAdKCgBGKK?list=PLnI9xbPdZUAmUL8htSl6vToPQRRN3hhFp

[c]: (xyz = 0 et isc = 1) ou (((xyz = 0 et isc = 1) ou (isc = 0)) et (isc = 0))

[d]: ((x-1) (y-1) (z-1) = 0 et isc = 2) ou (((xyz = 0 et isd = 2) ou (isc = 0)) et (isc = 0))

...

connectez ces formules en suivant la logique:

la logique et la somme des carrés des équations

la logique ou est le produit des équations

et vous aurez l'équation totale

somme express et tu as formule totale de somme

alors somme & 1 est c, somme & 2 est d, somme & 4 est e, somme & 5 est f

après cela, vous pouvez former un tableau prédéfini où l'index de l'élément de chaîne correspondrait à la chaîne prête.

array [sum] vous donne la chaîne.

0
Sergei

Vous pouvez utiliser le dictionnaire:

x = 0
y = 1
z = 3
list=[]
dict = {0: 'c', 1: 'd', 2: 'e', 3: 'f'}
if x in dict:
    list.append(dict[x])
else:
    pass

if y in dict:
    list.append(dict[y])
else:
    pass
if z in dict:
    list.append(dict[z])
else:
    pass

print list
0
Rohit Gawas