"elif" ในเงื่อนไขรายการเพื่อความเข้าใจ


129

เราสามารถใช้elifในการทำความเข้าใจรายการได้หรือไม่?

ตัวอย่าง:

l = [1, 2, 3, 4, 5]

for values in l:
    if values==1:
        print 'yes'
    elif values==2:
        print 'no'
    else:
        print 'idle'

เราสามารถรวมความเข้าใจelifในรายการของเราในลักษณะเดียวกันกับรหัสด้านบนได้หรือไม่

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

['yes', 'no', 'idle', 'idle', 'idle']

จนถึงตอนนี้ฉันใช้ifและelseเข้าใจในรายการเท่านั้น

คำตอบ:


250

นิพจน์เงื่อนไขของ Python ได้รับการออกแบบมาสำหรับกรณีการใช้งานประเภทนี้:

>>> l = [1, 2, 3, 4, 5]
>>> ['yes' if v == 1 else 'no' if v == 2 else 'idle' for v in l]
['yes', 'no', 'idle', 'idle', 'idle']

หวังว่านี่จะช่วยได้ :-)


5
มีประวัติที่น่าสนใจในไวยากรณ์ หลายปีก่อนคำนำ "นิพจน์ระดับตติยภูมิ" เป็นหนึ่งในห้าการเปลี่ยนแปลงที่มีผู้ขอมากที่สุดในภาษา เนื่องจาก Guido van Rossum ได้รับการออกแบบอย่างชัดเจนให้เป็นภาษาที่ใช้คำสั่งเขาจึงต่อต้านอย่างหนักแน่นเป็นเวลานาน (การแสดงออกในระดับตติยภูมิและโดยเฉพาะอย่างยิ่งการละเมิดเป็นแหล่งที่มาของความคลุมเครือในรหัส) เมื่อเขายอมจำนนในที่สุดเขาก็ประกาศว่าเขาจงใจเลือกไวยากรณ์ที่ทำให้ท้อแท้มากเกินไป ตามปกติเขาทำงานออกแบบที่หรูหราอย่างไรก็ตาม
holdenweb

1
Ternary, dammit (เขาเขียนโดยสังเกตเห็นความผิดพลาดของ dyslexic สายเกินไปที่จะแก้ไข)
holdenweb

2
ในขณะที่ฉันโหวตคำตอบนี้ฉันต้องการพูดถึงสิ่งนี้: สำหรับ if / else 1 คู่นั้นอ่านง่าย 2 คู่: มันยากที่จะเข้าใจ ไม่พูดถึง 3 คู่เลย หากนิพจน์ต้องการ 3 คู่ขึ้นไปพจนานุกรมหรือฟังก์ชันแยกกันจะช่วยให้อ่านและทำความเข้าใจได้ง่ายขึ้น
Hai Vu

1
ฉันไม่ต้องการเพิ่มวิธีแก้ปัญหาสำหรับปัญหานี้ แต่เป็นการเตือนความจำของรหัสที่สะอาด: เนื่องจากความเข้าใจในรายการนี้มีเงื่อนไขสามข้อจึงอาจถูก refactored เป็นวิธีการที่อธิบายได้มากขึ้น ประเด็นของฉันคือmartinfowler.com/bliki/FunctionLength.html :)
Alvaro Cavalcanti

ฉันสะดุดกับกรณีที่ฉันต้องการ elif แต่มีเพียงสองค่า จากตัวอย่างนี้ฉันจำเป็น['yes', 'no']ต้องทำ ในการดำเนินการนี้คุณสามารถทำได้: ['yes' if v == 1 else 'no' for v in l if values in [1,2]]. ขณะนี้ฉันยังคิดวิธีที่สะอาดกว่านี้ไม่ได้
dTanMan

48
>>> d = {1: 'yes', 2: 'no'}
>>> [d.get(x, 'idle') for x in l]
['yes', 'no', 'idle', 'idle', 'idle']

4
ฉันคิดว่าแบบฟอร์มนี้ย่อยง่ายกว่าการพยายามทำตรรกะ if / else ที่ยาวและซับซ้อนจริงๆภายในรายการ comp
jdi

5
@jdi แม้ว่าการแสดงออกตามเงื่อนไขอาจไม่ตรงกับรสนิยมของคุณ แต่ก็เป็นเช่นนั้นออกแบบมาโดยเฉพาะเพื่อจัดการกับโซ่ if-elif-elif-else ตามที่ OP ร้องขอ 'A' if grade>=90 else 'B' if grade>=80 else 'C' if grade>=70 else 'F'พวกเขาจะไม่ยากที่จะเรียนรู้และสง่างามสามารถจัดการกับสถานการณ์ที่ไม่คล้อยตามตรรกะการค้นหาพจนานุกรม:
Raymond Hettinger

1
หากมีข้อได้เปรียบของการกำหนดdนอกความเข้าใจ?
Chris_Rands

เหตุผลที่ฉันชอบความเข้าใจในรายการมากกว่าคือมันอ่านเหมือนกับภาษาอังกฤษ แม้แต่คนที่ไม่ใช่โปรแกรมเมอร์ก็สามารถเข้าใจได้ว่ามันทำอะไร ด้วยวิธีนี้คุณต้องเข้าใจวิธีการ dict.get ()
Tim Skov Jacobsen

26

คุณสามารถเรียงลำดับได้

โปรดทราบว่าเมื่อคุณใช้ sytax เช่น:

['yes' if v == 1 else 'no' for v in l]

คุณกำลังใช้รูปแบบ ternary ของหาก / อื่นประกอบ (ถ้าคุณคุ้นเคยกับภาษาเช่น C นี้เป็นเหมือน?:การสร้าง: (v == 1 ? 'yes' : 'no'))

รูปแบบประกอบของตัวดำเนินการ if / else ไม่มีตัวดำเนินการ 'elif' ในตัว แต่คุณสามารถจำลองได้ในเงื่อนไข 'else':

['yes' if v == 1 else 'no' if v == 2 else 'idle' for v in l]

นี่ก็เหมือนกับการพูดว่า:

for v in l:
    if v == 1 :
        print 'yes'
    else:
        if v == 2:
            print 'no'
        else:
            print 'idle'

ดังนั้นจึงไม่มีโครงสร้าง 'elif' โดยตรงอย่างที่คุณถาม แต่สามารถจำลองได้ด้วยคำสั่ง if / else ที่ซ้อนกัน


1
รหัสย่อหน้าสุดท้ายเป็นข้อมูลเชิงลึกขอบคุณมาก!
devianceee


2

คุณสามารถใช้ความเข้าใจรายการคือคุณกำลังจะสร้างรายการอื่นจากต้นฉบับ

>>> l = [1, 2, 3, 4, 5]
>>> result_map = {1: 'yes', 2: 'no'}
>>> [result_map[x] if x in result_map else 'idle' for x in l]
['yes', 'no', 'idle', 'idle', 'idle']

2

อีกวิธีง่ายๆคือใช้การทำความเข้าใจรายการตามเงื่อนไขดังนี้:

l=[1,2,3,4,5]
print [[["no","yes"][v==1],"idle"][v!=1 and v!=2] for v in l]

ให้คุณทอดสมอที่ถูกต้อง:

['ใช่', 'ไม่', 'ไม่ได้ใช้งาน', 'ไม่ได้ใช้งาน', 'ไม่ได้ใช้งาน']

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.