if / else ในรายการความเข้าใจ


903

ฉันจะทำสิ่งต่อไปนี้ใน Python ได้อย่างไร

row = [unicode(x.strip()) for x in row if x is not None else '']

เป็นหลัก:

  1. แทนที่ Nones ทั้งหมดด้วยสตริงว่างแล้ว
  2. ดำเนินฟังก์ชั่น

คำตอบ:


1457

คุณสามารถทำเช่นนั้นได้ทั้งหมด มันเป็นเพียงปัญหาการสั่งซื้อ:

[unicode(x.strip()) if x is not None else '' for x in row]

โดยทั่วไปแล้ว

[f(x) if condition else g(x) for x in sequence]

และสำหรับรายการความเข้าใจที่มีifเงื่อนไขเท่านั้น

[f(x) for x in sequence if condition]

โปรดทราบว่าสิ่งนี้ใช้โครงสร้างภาษาที่แตกต่างกันซึ่งเป็นการแสดงออกแบบมีเงื่อนไขซึ่งตัวมันเองไม่ได้เป็นส่วนหนึ่งของไวยากรณ์ความเข้าใจในขณะที่ส่วนifหลังfor…inของรายการนั้นเป็นส่วนหนึ่งของความเข้าใจในรายการและใช้ในการกรององค์ประกอบจากแหล่งที่มา


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

value = 123
print(value, 'is', 'even' if value % 2 == 0 else 'odd')

141
โปรดทราบว่าไวยากรณ์ if / else ที่นี่ตอนนี้เป็น "ตัวดำเนินการที่ประกอบไปด้วย" และไม่แสดงไวยากรณ์ความเข้าใจ
Adam Vandenberg

8
นั่นเป็นเหตุผลที่ฉันชอบใส่ผู้ประกอบการในวงเล็บมันทำให้ชัดเจนว่ามันเป็นเพียงการแสดงออกปกติไม่ใช่ความเข้าใจ
Jochen Ritzel

17
ดังนั้นเคล็ดลับคือ "ในการบีบอัดรายการฉันเขียนถ้าก่อนหน้านั้นฉันต้องเพิ่มส่วนอื่นด้วย" เพราะถ้าฉันl = [ 2, 3, 4, 5]แล้วก็[x if x % 2 == 0 for x in l]ให้ฉันข้อผิดพลาดในขณะที่[x if x % 2 == 0 else 200 for x in l]ทำงาน [ x for x in l if x % 2 == 0]ใช่ฉันรู้ว่าการกรองฉันควรจะเขียน ขออภัยที่อนิจจา ขอบคุณสำหรับคำตอบ.
Grijesh Chauhan

5
เอกสารหลามพูดถึงผู้ประกอบการที่ประกอบไปด้วย โปรดทราบว่ามันต้องใช้อย่างอื่นหรือไม่ทำงาน
naught101

4
@Drewdin List comprehensions ไม่รองรับการหยุดพักระหว่างการทำซ้ำ คุณจะต้องใช้วงปกติแล้ว
กระตุ้น

44

ทางเดียว:

def change(f):
    if f is None:
        return unicode(f.strip())
    else:
        return ''

row = [change(x) for x in row]

แม้ว่าคุณจะมี:

row = map(change, row)

หรือคุณสามารถใช้แลมบ์ดาอินไลน์


13
นี่เป็นเทคนิคที่ดี (อาจจะ) ที่จะใช้เมื่อคุณต้องจัดการกับข้อยกเว้นที่เป็นไปได้จากifนิพจน์หรือรหัสในelseบล็อกคำสั่งหรือ คำตอบที่ยอมรับได้ดีกว่าสำหรับกรณีง่าย ๆ
martineau

37

นี่เป็นอีกตัวอย่างที่เป็นตัวอย่าง:

>>> print(", ".join(["ha" if i else "Ha" for i in range(3)]) + "!")
Ha, ha, ha!

มันใช้ประโยชน์จากความจริงที่ว่าif iประเมินFalseสำหรับ0และTrueสำหรับค่าอื่น ๆ range()ทั้งหมดที่สร้างโดยฟังก์ชั่น ดังนั้นรายการความเข้าใจจะประเมินดังนี้:

>>> ["ha" if i else "Ha" for i in range(3)]
['Ha', 'ha', 'ha']

37

ปัญหาที่เฉพาะเจาะจงได้รับการแก้ไขแล้วในคำตอบก่อนหน้าดังนั้นฉันจะพูดถึงความคิดทั่วไปของการใช้เงื่อนไขภายในรายการความเข้าใจ

นี่คือตัวอย่างที่แสดงให้เห็นว่าสามารถเขียนเงื่อนไขในความเข้าใจของรายการได้อย่างไร:

X = [1.5, 2.3, 4.4, 5.4, 'n', 1.5, 5.1, 'a']     # Original list

# Extract non-strings from X to new list
X_non_str = [el for el in X if not isinstance(el, str)]  # When using only 'if', put 'for' in the beginning

# Change all strings in X to 'b', preserve everything else as is
X_str_changed = ['b' if isinstance(el, str) else el for el in X]  # When using 'if' and 'else', put 'for' in the end

โปรดทราบว่าในรายการแรกที่เข้าใจสำหรับX_non_strการสั่งซื้อคือ:

การแสดงออก สำหรับ รายการ ใน iterable ถ้า เงื่อนไข

และในรายการสุดท้ายที่เข้าใจX_str_changedคือลำดับคือ:

expression1 ถ้า condition else expression2 สำหรับ item ใน iterable

ฉันมักจะพบว่ามันยากที่จะจำไว้ว่าexpresseion1จะต้องมีก่อนถ้าและExpression2จะเป็นหลังจากที่มีคนอื่น หัวของฉันต้องการให้ทั้งก่อนและหลัง

ฉันเดาว่ามันถูกออกแบบมาเช่นนั้นเพราะคล้ายกับภาษาปกติเช่น "ฉันต้องการอยู่ข้างในถ้าฝนตกมิฉะนั้นฉันก็อยากออกไปข้างนอก"

ในภาษาอังกฤษธรรมดาความเข้าใจในรายการทั้งสองประเภทที่กล่าวถึงข้างต้นอาจกล่าวได้ว่า:

มีเพียงif:

extract_apple สำหรับ apple ใน box_of_apples ถ้า apple_is_ripe

และด้วย if/else

mark_apple หาก apple_is_ripe ปล่อยให้แอปเปิ้ล_it_unmark อื่น ๆ อยู่ในbox_of_apples


7

โซลูชันอื่น ๆ นั้นยอดเยี่ยมสำหรับงานเดี่ยวif/ elseงานสร้าง อย่างไรก็ตามข้อความไตรภาคภายในรายการความเข้าใจนั้นยากที่จะอ่าน

การใช้ฟังก์ชั่นช่วยในการอ่าน แต่การแก้ปัญหาดังกล่าวเป็นการยากที่จะขยายหรือปรับในเวิร์กโฟลว์ที่การทำแผนที่เป็นอินพุต พจนานุกรมสามารถบรรเทาข้อกังวลเหล่านี้:

row = [None, 'This', 'is', 'a', 'filler', 'test', 'string', None]

d = {None: '', 'filler': 'manipulated'}

res = [d.get(x, x) for x in row]

print(res)

['', 'This', 'is', 'a', 'manipulated', 'test', 'string', '']

1

มันเกี่ยวกับวิธีการทำ list comprehension

โปรดจำไว้ว่า:

[ expression for item in list if conditional ]

เทียบเท่ากับ:

for item in list:
    if conditional:
        expression

ในกรณีที่expressionอยู่ในรูปแบบที่แตกต่างกันเล็กน้อย (คิดว่าการเปลี่ยนเรื่องและคำกริยาในประโยค)

ดังนั้นรหัสของคุณ[x+1 for x in l if x >= 45]ทำสิ่งนี้:

for x in l:
    if x >= 45:
        x+1

อย่างไรก็ตามรหัสนี้[x+1 if x >= 45 else x+5 for x in l]ทำสิ่งนี้ (หลังจากจัดเรียงใหม่expression):

for x in l:
    if x>=45: x+1
    else: x+5

0

ไม่จำเป็นต้องมี ternary หาก / / / อื่น ๆ ในความคิดของฉันคำถามของคุณเรียกหาคำตอบนี้:

row = [unicode((x or '').strip()) for x in row]

0

ทำรายการจากรายการใน iterable

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

[expression1(item)                                        for item in iterable]

[expression1(item) if conditional1                        for item in iterable]

[expression1(item) if conditional1 else expression2(item) for item in iterable]

[expression1(item) if conditional1 else expression2(item) for item in iterable if conditional2]

ค่าของitemไม่จำเป็นต้องนำมาใช้ในใด ๆ ของคำสั่งเงื่อนไข conditional3สามารถใช้เป็นสวิทช์ที่จะเพิ่มหรือไม่เพิ่มมูลค่าให้กับรายการที่ส่งออก

ตัวอย่างเช่นในการสร้างรายการใหม่ที่กำจัดสตริงว่างหรือสตริงช่องว่างจากรายการสตริงดั้งเดิม:

newlist = [s for s in firstlist if s.strip()]

1
ข้อที่สองให้ข้อผิดพลาดตามที่ Tim ตอบไว้ในความคิดเห็นของเขาดูคำสั่งเงื่อนไขในเอกสาร python ซึ่งค่อนข้างอ่านไม่ได้สำหรับฉัน สรุป: this if condition else thatอนุญาตให้ใช้ได้เฉพาะนิพจน์ปกติเท่านั้น ไม่ใช่value = this if condition(ซึ่งสามารถทำได้ด้วยvalue = this if condition else None)
Anderium

0

คุณสามารถรวมตรรกะตามเงื่อนไขในความเข้าใจ:

 ps = PorterStemmer()
 stop_words_english = stopwords.words('english')
 best = sorted(word_scores.items(), key=lambda x: x[1], reverse=True)[:10000]
 bestwords = set([w for w, s in best])


 def best_word_feats(words):
   return dict([(word, True) for word in words if word in bestwords])

 # with stemmer
 def best_word_feats_stem(words):
   return dict([(ps.stem(word), True) for word in words if word in bestwords])

 # with stemmer and not stopwords
 def best_word_feats_stem_stop(words):
   return dict([(ps.stem(word), True) for word in words if word in bestwords and word not in stop_words_english])

-2
# coding=utf-8

def my_function_get_list():
    my_list = [0, 1, 2, 3, 4, 5]

    # You may use map() to convert each item in the list to a string, 
    # and then join them to print my_list

    print("Affichage de my_list [{0}]".format(', '.join(map(str, my_list))))

    return my_list


my_result_list = [
   (
       number_in_my_list + 4,  # Condition is False : append number_in_my_list + 4 in my_result_list
       number_in_my_list * 2  # Condition is True : append number_in_my_list * 2 in my_result_list
   )

   [number_in_my_list % 2 == 0]  # [Condition] If the number in my list is even

   for number_in_my_list in my_function_get_list()  # For each number in my list
]

print("Affichage de my_result_list [{0}]".format(', '.join(map(str, my_result_list))))

(venv) $ python list_comp.py
Affichage de my_list [0, 1, 2, 3, 4, 5]
Affichage de my_result_list [0, 5, 4, 7, 8, 9]

ดังนั้นสำหรับคุณ: row = [('', unicode(x.strip()))[x is not None] for x in row]


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