如何测试多个变量对单个值的相等性?

我正在尝试创建一个将多个变量与一个整数进行比较并输出一个由三个字母组成的字符串的函数。我想知道是否有办法将其翻译成Python。所以说:

x = 0y = 1z = 3mylist = []
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")

这将返回以下列表:

["c", "d", "f"]
482715 次浏览

您误解了布尔表达式的工作原理;它们不像英语句子那样工作,并且猜测您在这里谈论的是所有名称的相同比较。

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

xy在其他情况下自行评估(False如果0True否则)。

您可以使用针对一个元组的遏制测试来缩短它:

if 1 in (x, y, z):

或者更好的是:

if 1 in {x, y, z}:

使用a#0来利用恒成本成员资格测试(即in需要固定的时间量,无论左侧操作数是什么)。

补充说明

当您使用or时,python将运算符的每一面视为单独表达式。表达式x or y == 1首先被视为x的布尔测试,然后如果是False,则测试表达式y == 1

这是由于运算符优先级or运算符的优先级低于==测试,因此后者被评估第一

然而,即使这是没有的情况,并且表达式x or y or z == 1实际上被解释为(x or y or z) == 1,这仍然不会做你期望它做的事情。

x or y or z将评估为“truthy”的第一个参数,例如不是False、数字0或空(有关Python在布尔上下文中认为假的详细信息,请参阅布尔表达式)。

因此,对于值x = 2; y = 1; z = 0x or y or z将解析为2,因为这是参数中的第一个类真值。然后2 == 1将是False,即使y == 1将是True

这同样适用于逆;针对单个变量测试多个值;x == 1 or 2 or 3会因同样的原因失败。使用x == 1 or x == 2 or x == 3x in {1, 2, 3}

x or y or z == 0的直接方法是

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

但我不认为你喜欢它。:)这种方式是丑陋的。

另一种方法(更好的)是:

0 in (x, y, z)

顺便说一句,很多if可以写成这样

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

您的问题更容易通过字典结构解决,例如:

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

要检查一个值是否包含在一组变量中,您可以使用内置模块itertoolsoperator

例如:

进口:

from itertools import repeatfrom operator import contains

声明变量:

x = 0y = 1z = 3

创建值的映射(按照您要检查的顺序):

check_values = (0, 1, 3)

使用itertools允许重复变量:

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

最后,使用map函数创建一个迭代器:

checker = map(contains, check_vars, check_values)

然后,当检查值(按原始顺序)时,使用next()

if next(checker)  # Checks for 0# Do somethingpasselif next(checker)  # Checks for 1# Do somethingpass

等…

这比lambda x: x in (variables)有优势,因为operator是一个内置模块,比使用lambda更快、更高效,后者必须创建一个自定义的就地函数。

检查列表中是否有非零(或False)值的另一个选项:

not (x and y and z)

等效:

not all((x, y, z))

我认为这样做会更好:

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]

输出:

print validate(0, 8, 9)cprint validate(9, 8, 9)Noneprint validate(9, 8, 2)e
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]

如果你想使用if,则以下语句是另一种解决方案:

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)

如果你非常非常懒,你可以把值放在数组中。例如

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

你也可以把数字和字母放在字典里,但这可能比简单的if语句复杂得多。这就是你试图额外懒惰的结果:)

还有一件事,你的

if x or y or z == 0:

会编译,但不是以你想要的方式编译。当你简单地把一个变量放在if语句中时(示例)

if b

程序将检查变量是否为空。编写上述语句的另一种方法(更有意义)是

if bool(b)

Bool是python中的一个内置函数,它基本上执行验证布尔语句的命令(如果你不知道那是什么,它就是你现在在if语句中尝试做的:))

我发现的另一个懒惰的方法是:

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

Set是这里的好方法,因为它对变量进行排序,这似乎是您的目标。无论参数的顺序如何,{z,y,x}都是{0,1,3}

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

这样,整个解是O(n)。

这段代码可能会有帮助

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;

正如Martijn Pieters所说,正确且最快的格式是:

if 1 in {x, y, z}:

根据他的建议,您现在将有单独的if语句,以便Python将读取每个语句,无论前者是True还是False。例如:

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

这将工作,但是如果你可以使用字典(看看我在那里做了什么),你可以通过制作一个初始字典将数字映射到你想要的字母来清理它,然后只需使用for循环:

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

这里提供的所有优秀答案都集中在原楼主的具体要求上,集中在Martijn Pieters提出的if 1 in {x,y,z}解决方案上。
他们忽略的是这个问题更广泛的含义:
如何针对多个值测试一个变量?
如果使用字符串,提供的解决方案将不适用于部分命中,例如:
测试字符串“Wild”是否在多个值中

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

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

在这种情况下,最容易转换为字符串

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

然而,应该注意的是,正如@codeforester所提到的,这个方法会丢失单词boundries,例如:

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

3个字母rot确实以组合形式存在于列表中,但不是作为单个单词存在。测试“腐”会失败,但如果列表项之一是“在地狱中腐烂”,也会失败。
结果是,如果使用此方法,请小心您的搜索条件,并注意它确实有此限制。

单线解决方案:

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

或:

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

你可以使用字典:

x = 0y = 1z = 3list=[]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:passif z in dict:list.append(dict[z])else:pass
print list

在Python中表示伪代码的最pythonic方式是:

x = 0y = 1z = 3mylist = []
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")

看起来你正在构建某种凯撒密码。

更普遍的方法是这样的:

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

产出

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

不确定这是否是代码所需的副作用,但输出的顺序将始终排序。

如果这是你想要的,最后一行可以改为:

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

用一个值测试多个变量:if 1 in {a,b,c}:

使用一个变量测试多个值:if a in {1, 2, 3}:

它可以很容易地完成

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

您可以尝试下面显示的方法。在此方法中,您可以自由指定/输入您希望输入的变量数量。

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']

也许您需要设置输出位的直接公式。

x=0 or y=0 or z=0   is equivalent to x*y*z = 0
x=1 or y=1 or z=1   is equivalent to (x-1)*(y-1)*(z-1)=0
x=2 or y=2 or z=2   is equivalent to (x-2)*(y-2)*(z-2)=0

让我们映射到位:'c':1 'd':0xb10 'e':0xb100 'f':0xb1000

isc的关系(is'c'):

if xyz=0 then isc=1 else isc=0

如果公式https://youtu.be/KAdKCgBGK0k?list=PLnI9xbPdZUAmUL8htSl6vToPQRRN3hhFp&;t=315,则使用数学

[c]:(xyz=0 and isc=1) or (((xyz=0 and isc=1) or (isc=0)) and (isc=0))

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

通过以下逻辑连接这些公式:

  • 逻辑and是方程式的平方和
  • 逻辑0是方程式的乘积

你会得到一个总等式表示和,你有总和的公式

那么sum&1是c,sum&2是d,sum&4是e,sum&5是f

在此之后,您可以形成预定义的数组,其中字符串元素的索引将对应于就绪字符串。

array[sum]为您提供字符串。

这将帮助你。

def test_fun(val):x = 0y = 1z = 2myList = []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);

你可以把这个

x = 0y = 1z = 3

在一个变量中。

In [1]: xyz = (0,1,3,)In [2]: mylist = []

更改我们的条件为:

In [3]: if 0 in xyz:...:     mylist.append("c")...: if 1 in xyz:...:     mylist.append("d")...: if 2 in xyz:...:     mylist.append("e")...: if 3 in xyz:...:     mylist.append("f")

输出:

In [21]: mylistOut[21]: ['c', 'd', 'f']

如果没有字典,试试这个解决方案:

x, y, z = 0, 1, 3offset = ord('c')[chr(i + offset) for i in (x,y,z)]

并给出:

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

问题

而测试多个值的模式

>>> 2 in {1, 2, 3}True>>> 5 in {1, 2, 3}False

非常可读,并在许多情况下工作,有一个陷阱:

>>> 0 in {True, False}True

但我们想拥有

>>> (0 is True) or (0 is False)False

解决方案

上一个表达式的一个概括是基于ytpilai的答案:

>>> any([0 is True, 0 is False])False

它可以写为

>>> any(0 is item for item in (True, False))False

虽然这个表达式返回正确的结果,但它的可读性不如第一个表达式:-(

你可以通过两种方式发展它

    def compareVariables(x,y,z):mylist = []if x==0 or y==0 or z==0:mylist.append('c')if  x==1 or y==1 or z==1:mylist.append('d')if  x==2 or y==2 or z==2:mylist.append('e')if  x==3 or y==3 or z==3:mylist.append('f')else:print("wrong input value!")print('first:',mylist)
compareVariables(1, 3, 2)

    def compareVariables(x,y,z):mylist = []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')if 3 in (x,y,z):mylist.append('f')else:print("wrong input value!")print('second:',mylist)
compareVariables(1, 3, 2)

这里有另一种方法来做到这一点:

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

它是列表理解任何关键字的混合。

or不像这个答案解释了那样工作。

虽然一般的答案是使用

if 0 in (x, y, z):...

这不是解决特定问题的最佳方法。在你的情况下,你正在做重复测试,因此值得组合这些变量中的

values = {x, y, z}
if 0 in values:mylist.append("c")
if 1 in values:mylist.append("d")

我们可以使用字典来简化它-这将导致相同的值:

mappings = {0: "c", 1: "d", ...}for k in mappings:if k in values:mylist.append(mappings[k])

或者,如果mylist的顺序是任意的,您可以遍历并将它们与映射匹配:

mappings = {0: "c", 1: "d", ...}for v in (x, y, z):if v in mappings:mylist.append(mappings[v])

不带if示例的用法:

x,y,z = 0,1,3values = {0:"c",1:"d",2:"e",3:"f"} # => as if usagemy_list = [values[i] for i in (x,y,z)]
print(my_list)

首先,对OR条件的更正:

你需要说:

if x == 0 or y == 0 or z == 0:

原因是“或”将条件分成了不同的逻辑部分。你最初的陈述是这样写的,这些部分是:

xyz == 0   // or 1, 2, 3 depending on the if statement

最后一部分很好——检查z==0,例如——但前两部分本质上只是说if xif y。由于整数总是计算为True,除非它们是0,这意味着当xy不等于0时,你条件的第一部分总是True(在y的情况下总是,因为你有y = 1,导致你的整个条件(因为OR的工作方式)总是True

为了避免这种情况,您需要确保条件的所有部分(OR的每一面)都有意义(您可以通过假装OR语句的另一面不存在来做到这一点)。这就是您确认OR条件是否定义正确的方法。

您可以像这样单独编写语句:

if x == 0if y == 0if z == 0

这意味着OR关键字的正确mergin是:

if x == 0 or y == 0 or z == 0

二、如何解决问题:

你基本上想要检查是否有任何变量与给定的整数匹配,如果是,则在一对一映射中为其分配一个与之匹配的字母。你想对某个整数列表执行此操作,以便输出是一个字母列表。你会这样做:

def func(x, y, z):
result = []
for integer, letter in zip([0, 1, 2, 3], ['c', 'd', 'e', 'f']):if x == integer or y == integer or z == integer:result.append(letter)            
return result        

同样,您可以使用LIST COMPREHENSION更快地实现相同的结果:

def func(x, y, z):
return [letterfor integer, letter in zip([0, 1, 2, 3], ['c', 'd', 'e', 'f'])if x == integer or y == integer or z == integer]    
    
#selection: a=np.array([0,1,3])
#options: np.diag(['c','d','e','f'])array([['c', '', '', ''],['', 'd', '', ''],['', '', 'e', ''],['', '', '', 'f']], dtype='<U1')

现在我们可以使用一个作为[row, cols]选择器,它的作用就像任何(…)条件一样:

#list of options[sel,sel]: np.diag(['c','d','e','f'])[a,a]
array(['c', 'd', 'f'], dtype='<U1')

要针对单个值测试多个变量:

将变量包装在集合对象中,例如{a, b, c}。使用in运算符测试值是否存储在任何变量中。如果值存储在至少一个变量中,in运算符将返回True。

# ✅ test multiple variables against single value using tuple
if 'a' in (a, b, c):print('value is stored in at least one of the variables')
# ---------------------------------------------------------
# ✅ test multiple variables against single value using tuple
if 'a' in {a, b, c}:print('value is stored in at least one of the variables')
# ---------------------------------------------------------

# ✅ test multiple variables against single value (OR operator chaining)if a == 'a' or b == 'a' or c == 'a':print('value is stored in at least one of the variables')

来源:https://bobbyhadz.com/blog/python-test-multiple-variables-against-single-value