subplot python




¿Cómo probar múltiples variables contra un valor? (12)

Estoy tratando de hacer una función que compare varias variables con un entero y genere una cadena de tres letras. Me preguntaba si había una manera de traducir esto a Python. Así que di:

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")

que devolvería una lista de

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

¿Es algo como esto posible?


Creo que esto lo manejará mejor:

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]

Salida:

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

Establecer es el buen enfoque aquí, porque ordena las variables, lo que parece ser tu objetivo aquí. {z,y,x} es {0,1,3} cualquiera que sea el orden de los parámetros.

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

De esta manera, toda la solución es O (n).


La forma directa de escribir x or y or z == 0 es

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

Pero no creo, te guste. :) Y esta manera es fea.

La otra manera (una mejor) es:

0 in (x, y, z)

Por cierto un montón de if s podría escribirse como algo como esto

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

La forma más mnemotécnica de representar su pseudocódigo en Python sería:

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")

Para verificar si un valor está contenido dentro de un conjunto de variables, puede usar los módulos incorporados itertools y el operator .

Por ejemplo:

Importaciones:

from itertools import repeat
from operator import contains

Declarar variables:

x = 0
y = 1
z = 3

Crea mapeo de valores (en el orden que quieras verificar):

check_values = (0, 1, 3)

Usa itertools para permitir la repetición de las variables:

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

Finalmente, use la función de map para crear un iterador:

checker = map(contains, check_vars, check_values)

Luego, al verificar los valores (en el orden original), use next() :

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

etc ...

Esto tiene una ventaja sobre la lambda x: x in (variables) porque el operator es un módulo incorporado y es más rápido y más eficiente que usar lambda que tiene que crear una función personalizada en el lugar.

Otra opción para verificar si hay un valor distinto de cero (o Falso) en una lista:

not (x and y and z)

Equivalente:

not all((x, y, z))

Parece que estás construyendo una especie de cifrado César.

Un enfoque mucho más generalizado es este:

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

salidas

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

No estoy seguro si es un efecto secundario deseado de su código, pero el orden de su salida siempre se ordenará.

Si esto es lo que quieres, la última línea se puede cambiar a:

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

Se puede hacer fácilmente como

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

Si desea utilizar if, else las siguientes afirmaciones son otra solución:

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)

Su problema se resuelve más fácilmente con una estructura de diccionario como:

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

Todas las excelentes respuestas proporcionadas aquí se concentran en el requisito específico del póster original y se concentran en la solución if 1 in {x,y,z} presentada por Martijn Pieters.
Lo que ignoran es la implicación más amplia de la pregunta:
¿Cómo pruebo una variable contra múltiples valores?
La solución provista no funcionará para resultados parciales si se usan cadenas, por ejemplo:
Probar si la cadena "Wild" está en múltiples valores

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

o

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

para este escenario es más fácil convertir a una cadena

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

Sin embargo, se debe tener en cuenta, como lo menciona @codeforester , que los límites de palabras se pierden con este método, como en:

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

las 3 letras de rot existen en combinación en la lista pero no como una palabra individual. Las pruebas de "podredumbre" fallarían, pero si uno de los elementos de la lista fuera "podredumbre en el infierno", también fallaría.
El resultado final es ser cuidadoso con los criterios de búsqueda si utiliza este método y tenga en cuenta que tiene esta limitación.


Usted malinterpreta cómo funcionan las expresiones booleanas; no funcionan como una oración en inglés y supongo que estás hablando de la misma comparación para todos los nombres aquí. Estás buscando:

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

y son evaluados por sí mismos ( False si 0 , True contrario).

Puedes acortar eso usando una prueba de contención contra una tupla :

if 1 in (x, y, z):

o mejor aún:

if 1 in {x, y, z}:

usar un set para aprovechar la prueba de membresía de costo constante ( in toma una cantidad fija de tiempo cualquiera que sea el operando de la izquierda).

Cuando usas or , python ve cada lado del operador como expresiones separadas . La expresión x or y == 1 se trata como una prueba booleana para x , luego, si eso es falso, se prueba la expresión y == 1 .

Esto se debe a la precedencia del operador . El operador or tiene una prioridad más baja que la prueba == , por lo que este último se evalúa primero .

Sin embargo, incluso si este no fuera el caso, y la expresión x or y or z == 1 realidad se interpretara como (x or y or z) == 1 lugar, esto no haría lo que usted espera que haga.

x or y or z evaluarán el primer argumento que sea "veraz", por ejemplo, no False , numérico 0 o vacío (consulte las expresiones booleanas para obtener información sobre lo que Python considera falso en un contexto booleano).

Así que para los valores x = 2; y = 1; z = 0 x = 2; y = 1; z = 0 x = 2; y = 1; z = 0 , x or y or z se resolvería en 2 , porque ese es el primer valor de tipo verdadero en los argumentos. Entonces 2 == 1 sería False , aunque y == 1 sería True .

Lo mismo se aplicaría a lo inverso; probando múltiples valores contra una sola variable; x == 1 or 2 or 3 fallarían por las mismas razones. Utilice x == 1 or x == 2 or x == 3 o x in {1, 2, 3} .


Solución anterior: Según lo declarado por Martijn Pieters, el formato correcto y más rápido es:

if 1 in {x, y, z}:

El único problema importante que no parece solucionarse es que desea que su lista de salida incluya cada letra después de una declaración de verdadero si.

Usando solo el consejo de Martijn Pieters, ahora tendrías:

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

Problema: la primera instrucción if devolvería verdadero, y nunca llegaría a la siguiente instrucción elif. Así que tu lista simplemente regresaría:

["c"]

Lo que quieres es tener sentencias if separadas para que Python lea cada afirmación si las primeras fueron verdaderas o falsas. Como:

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")
...

Esto funcionará, pero 'si' se siente cómodo usando diccionarios (vea lo que hice allí), puede limpiar esto haciendo un diccionario inicial que asigne los números a las letras que desea, y luego simplemente use un bucle 'for':

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




boolean-logic