จะทดสอบตัวแปรหลายตัวเทียบกับค่าได้อย่างไร?

Feb 27 2013

ฉันกำลังพยายามสร้างฟังก์ชันที่จะเปรียบเทียบตัวแปรหลายตัวเป็นจำนวนเต็มและแสดงสตริงของตัวอักษรสามตัว ฉันสงสัยว่ามีวิธีแปลสิ่งนี้เป็นภาษา Python หรือไม่ ดังนั้นพูดว่า:

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

ซึ่งจะส่งคืนรายการ:

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

สิ่งนี้เป็นไปได้หรือไม่?

คำตอบ

912 MartijnPieters Feb 27 2013 at 19:27

คุณเข้าใจผิดว่านิพจน์บูลีนทำงานอย่างไร มันใช้ไม่ได้เหมือนประโยคภาษาอังกฤษและเดาว่าคุณกำลังพูดถึงการเปรียบเทียบเหมือนกันสำหรับชื่อทั้งหมดที่นี่ คุณกำลังมองหา:

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

xและyได้รับการประเมินด้วยตนเอง ( Falseถ้า0เป็นTrueอย่างอื่น)

คุณสามารถย่อให้สั้นลงโดยใช้การทดสอบการกักกันกับทูเพิล :

if 1 in (x, y, z):

หรือยังดีกว่า:

if 1 in {x, y, z}:

โดยใช้asetเพื่อใช้ประโยชน์จากการทดสอบการเป็นสมาชิกแบบต้นทุนคงที่ ( inใช้เวลาคงที่ไม่ว่าจะเป็นตัวถูกดำเนินการด้านซ้าย)

เมื่อคุณใช้orpython จะมองเห็นแต่ละด้านของตัวดำเนินการเป็นนิพจน์แยกกัน นิพจน์x or y == 1จะถือว่าเป็นการทดสอบบูลีนxก่อนจากนั้นหากเป็นเท็จนิพจน์y == 1จะถูกทดสอบ

นี่คือสาเหตุที่สำคัญประกอบ orผู้ประกอบการมีความสำคัญต่ำกว่า==การทดสอบเพื่อให้หลังได้รับการประเมินครั้งแรก

อย่างไรก็ตามแม้ว่าจะไม่เป็นเช่นนั้นและx or y or z == 1จริงๆแล้วการแสดงออกนั้นถูกตีความว่า(x or y or z) == 1แทน แต่ก็ยังไม่เป็นไปตามที่คุณคาดหวัง

x or y or zจะประเมินเป็นอาร์กิวเมนต์แรกที่เป็น 'ความจริง' เช่นไม่ใช่Falseตัวเลข 0 หรือว่างเปล่า (ดูนิพจน์บูลีนสำหรับรายละเอียดเกี่ยวกับสิ่งที่ Python พิจารณาว่าเป็นเท็จในบริบทบูลีน)

ดังนั้นสำหรับค่าx = 2; y = 1; z = 0, x or y or zจะแก้2เพราะนั่นเป็นครั้งแรกที่จริงเช่นค่าในการขัดแย้ง จากนั้น2 == 1จะFalseแม้ว่าจะเป็นy == 1True

เช่นเดียวกันกับการผกผัน; การทดสอบหลายค่ากับตัวแปรเดียว x == 1 or 2 or 3จะล้มเหลวด้วยเหตุผลเดียวกัน ใช้x == 1 or x == 2 or x == 3หรือx in {1, 2, 3}.

96 dansalmo Jul 12 2013 at 04:56

ปัญหาของคุณแก้ไขได้ง่ายขึ้นด้วยโครงสร้างพจนานุกรมเช่น:

x = 0
y = 1
z = 3
d = {0: 'c', 1:'d', 2:'e', 3:'f'}
mylist = [d[k] for k in [x, y, z]]
67 ThatGuyRussell Aug 19 2015 at 09:34

ตามที่ระบุไว้โดย Martijn Pieters รูปแบบที่ถูกต้องและเร็วที่สุดคือ:

if 1 in {x, y, z}:

ใช้คำแนะนำของเขาที่คุณจะตอนนี้มีแยกต่างหากถ้างบเพื่อให้งูหลามจะอ่านคำสั่งแต่ละไม่ว่าจะเป็นอดีตหรือ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-loop:

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])
46 akaRem Jul 12 2013 at 04:16

วิธีเขียนโดยตรง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)

BTW จำนวนมาก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
35 ytpillai May 25 2015 at 10:53

หากคุณขี้เกียจมากคุณสามารถใส่ค่าในอาร์เรย์ได้ เช่น

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 x or y or z == 0:

จะรวบรวม แต่ไม่ใช่ในแบบที่คุณต้องการ เมื่อคุณใส่ตัวแปรในคำสั่ง if (ตัวอย่าง)

if b

โปรแกรมจะตรวจสอบว่าตัวแปรไม่เป็นโมฆะหรือไม่ อีกวิธีหนึ่งในการเขียนข้อความข้างต้น (ซึ่งเข้าท่ากว่า) ก็คือ

if bool(b)

Bool เป็นฟังก์ชัน inbuilt ใน python ซึ่งโดยพื้นฐานแล้วจะทำหน้าที่ในการตรวจสอบคำสั่งบูลีน (หากคุณไม่รู้ว่ามันคืออะไรนั่นคือสิ่งที่คุณพยายามทำในคำสั่ง if ของคุณตอนนี้ :))

อีกวิธีที่ขี้เกียจที่ฉันพบคือ:

if any([x==0, y==0, z==0])
33 GuiltyDolphin Jun 05 2014 at 00:09

ในการตรวจสอบว่ามีค่าอยู่ในชุดของตัวแปรหรือไม่คุณสามารถใช้โมดูล inbuilt itertoolsและoperator.

ตัวอย่างเช่น:

การนำเข้า:

from itertools import repeat
from operator import contains

ประกาศตัวแปร:

x = 0
y = 1
z = 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 something
    pass
elif next(checker)  # Checks for 1
    # Do something
    pass

ฯลฯ ...

สิ่งนี้มีข้อได้เปรียบเหนือlambda x: x in (variables)เพราะoperatorเป็นโมดูลในตัวและเร็วกว่าและมีประสิทธิภาพมากกว่าการใช้งานlambdaที่ต้องสร้างฟังก์ชัน in-place แบบกำหนดเอง

อีกทางเลือกหนึ่งในการตรวจสอบว่ามีค่าที่ไม่ใช่ศูนย์ (หรือเท็จ) ในรายการหรือไม่:

not (x and y and z)

เทียบเท่า:

not all((x, y, z))
31 B.M. Jun 10 2015 at 03:46

Set เป็นแนวทางที่ดีที่นี่เพราะมันสั่งตัวแปรสิ่งที่ดูเหมือนจะเป็นเป้าหมายของคุณที่นี่ {z,y,x}คือ{0,1,3}อะไรก็ตามที่อยู่ในลำดับของพารามิเตอร์

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

วิธีนี้วิธีแก้ปัญหาทั้งหมดคือ O (n)

31 RolfofSaxony Sep 10 2016 at 22:44

คำตอบที่ยอดเยี่ยมทั้งหมดที่ให้ไว้ที่นี่มุ่งเน้นไปที่ข้อกำหนดเฉพาะของโปสเตอร์ต้นฉบับและมุ่งเน้นไปที่if 1 in {x,y,z}โซลูชันที่นำเสนอโดย Martijn Pieters
สิ่งที่พวกเขาเพิกเฉยคือความหมายที่กว้างขึ้นของคำถาม:
ฉันจะทดสอบตัวแปรเดียวกับหลายค่าได้อย่างไร
โซลูชันที่ให้มาจะใช้ไม่ได้กับ Hit บางส่วนหากใช้สตริงเช่น
ทดสอบว่าสตริง "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ว่าขอบเขตของคำนั้นหายไปด้วยวิธีนี้เช่นเดียวกับใน:

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

มีตัวอักษร 3 ตัวrotอยู่รวมกันในรายการ แต่ไม่รวมเป็นคำแต่ละคำ การทดสอบ "เน่า" จะล้มเหลว แต่ถ้ารายการใดรายการหนึ่ง "เน่าในนรก" ก็จะล้มเหลวเช่นกัน
ผลลัพธ์ที่ได้โปรดใช้ความระมัดระวังกับเกณฑ์การค้นหาของคุณหากใช้วิธีนี้และโปรดทราบว่ามีข้อ จำกัด นี้

30 BhargavBoda Jan 13 2015 at 19:10

ฉันคิดว่าสิ่งนี้จะจัดการได้ดีขึ้น:

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)
c
print validate(9, 8, 9)
None
print validate(9, 8, 2)
e
30 hamid Apr 10 2015 at 10:29

หากคุณต้องการใช้ if, else คำสั่งต่อไปนี้เป็นวิธีแก้ปัญหาอื่น:

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)
26 SakshamVarma Feb 27 2015 at 08:31
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]
26 michaelzxc858 Jun 29 2015 at 14:03

รหัสนี้อาจเป็นประโยชน์

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;
12 SiddharthSatpathy Dec 03 2018 at 12:13

คุณสามารถลองใช้วิธีการที่แสดงด้านล่างนี้ ในวิธีนี้คุณจะมีอิสระในการระบุ / ป้อนจำนวนตัวแปรที่คุณต้องการป้อน

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']
10 VinayakKaniyarakkal Jun 05 2017 at 13:50

โซลูชันหนึ่งบรรทัด:

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)]
9 Sergei Feb 18 2019 at 00:55

บางทีคุณอาจต้องการสูตรโดยตรงสำหรับชุดบิตเอาต์พุต

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 (คือ 'c'):

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

ใช้สูตรคณิตศาสตร์ if https://youtu.be/KAdKCgBGK0k?list=PLnI9xbPdZUAmUL8htSl6vToPQRRN3hhFp&t=315

[ค]: (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คือผลรวมของกำลังสองของสมการ
  • ตรรกะorคือผลคูณของสมการ

และคุณจะมีผลรวมด่วนของสมการและคุณมีสูตรรวมของผลรวม

แล้ว sum & 1 คือ c ผลรวม & 2 คือ d ผลรวม & 4 คือ e ผลรวม & 5 คือ f

หลังจากนี้คุณสามารถสร้างอาร์เรย์ที่กำหนดไว้ล่วงหน้าซึ่งดัชนีขององค์ประกอบสตริงจะสอดคล้องกับสตริงที่พร้อม

array[sum] ให้สตริง

8 rsalmei Aug 06 2018 at 13:26

วิธี pythonic ที่สุดในการแสดงรหัสเทียมของคุณใน Python คือ:

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")
7 Seenivasan Nov 06 2018 at 21:26

ก็สามารถทำได้ง่ายๆเช่นกัน

for value in [var1,var2,var3]:
     li.append("targetValue")
5 alamin Sep 20 2018 at 09:18

ในการทดสอบตัวแปรหลายตัวด้วยค่าเดียว: if 1 in {a,b,c}:

ในการทดสอบหลายค่าด้วยตัวแปรเดียว: if a in {1, 2, 3}:

4 firelynx Aug 27 2018 at 16:45

ดูเหมือนว่าคุณกำลังสร้างการเข้ารหัสซีซาร์บางชนิด

แนวทางที่ครอบคลุมมากขึ้นคือ:

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])
3 Massifox Oct 11 2019 at 19:17

หากไม่มีคำสั่งให้ลองใช้วิธีนี้:

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

และให้:

['c', 'd', 'f']
2 RohitGawas Jul 31 2018 at 23:54

คุณสามารถใช้พจนานุกรม:

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
Mayur Apr 06 2019 at 05:03

สิ่งนี้จะช่วยคุณได้

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);
Serhii Sep 10 2019 at 01:23

คุณสามารถรวมสิ่งนี้ได้

x = 0
y = 1
z = 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]: mylist                                                                                
Out[21]: ['c', 'd', 'f']
fhgd Nov 06 2019 at 18:11

ปัญหา

ในขณะที่รูปแบบสำหรับการทดสอบหลายค่า

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

วิธีการแก้

การสรุปทั่วไปอย่างหนึ่งของนิพจน์ก่อนหน้านี้ขึ้นอยู่กับคำตอบจากytpillai :

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

ซึ่งสามารถเขียนเป็น

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

แม้ว่านิพจน์นี้จะส่งคืนผลลัพธ์ที่ถูกต้อง แต่ก็ไม่สามารถอ่านได้เหมือนกับนิพจน์แรก :-(