`elif` trong điều kiện hiểu danh sách


128

Chúng ta có thể sử dụng eliftrong việc hiểu danh sách không?

Thí dụ :

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

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

Chúng ta có thể đưa đoạn mã elifvào danh sách của chúng ta, theo cách tương tự như đoạn mã trên không?

Ví dụ, một câu trả lời như:

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

Cho đến nay, tôi chỉ sử dụng ifelsetrong việc hiểu danh sách.

Câu trả lời:


249

Các biểu thức điều kiện của Python được thiết kế chính xác cho loại trường hợp sử dụng này:

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

Hi vọng điêu nay co ich :-)


5
Có một số lịch sử thú vị trong cú pháp. Trong nhiều năm trước khi giới thiệu, "biểu thức bậc ba" là một trong năm thay đổi được yêu cầu nhiều nhất trong ngôn ngữ. Kể từ khi Guido van Rossum thiết kế rõ ràng nó như một ngôn ngữ dựa trên câu lệnh, ông kiên quyết chống lại trong một thời gian dài (các biểu thức cấp ba, và đặc biệt là việc lạm dụng chúng, là nguồn gây ra nhiều sự mù mờ trong mã). Cuối cùng, khi không chịu nổi, anh ta tuyên bố đã cố tình chọn một cú pháp không khuyến khích việc lạm dụng. Tuy nhiên, như thường lệ, anh ấy vẫn làm một công việc thiết kế trang nhã.
holdenweb

1
Ternary, chết tiệt (anh ấy đã viết, nhận ra lỗi khó đọc của mình quá muộn để chỉnh sửa).
holdenweb

2
Trong khi bỏ phiếu cho câu trả lời này, tôi muốn đề cập đến điều này: đối với 1 cặp if / else dễ đọc, 2 cặp: ngày càng khó hiểu hơn. Thậm chí không đề cập đến 3 cặp. Nếu biểu thức cần 3 cặp trở lên, một từ điển hoặc một hàm riêng biệt sẽ giúp mọi thứ dễ đọc và dễ hiểu hơn.
Hai Vu

1
Tôi không muốn thêm giải pháp cho vấn đề này, mà là một lời nhắc nhở về mã sạch: vì khả năng hiểu danh sách này có ba điều kiện, nó có thể được cấu trúc lại thành một phương pháp mô tả hơn. Quan điểm của tôi là thế này: martinfowler.com/bliki/FunctionLength.html :)
Alvaro Cavalcanti

Tôi tình cờ gặp một trường hợp mà tôi cần một elif, nhưng chỉ có hai giá trị. Sử dụng ví dụ này, tôi chỉ cần ['yes', 'no']được tạo ra. Để làm điều này, bạn có thể làm: ['yes' if v == 1 else 'no' for v in l if values in [1,2]]. Tôi hiện không thể nghĩ ra cách nào sạch hơn để làm điều này.
dTanMan

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

4
Tôi nghĩ rằng biểu mẫu này dễ hiểu hơn rất nhiều so với việc cố gắng thực hiện một logic if / else thực sự dài và phức tạp trong danh sách comp
jdi

5
@jdi Mặc dù biểu thức điều kiện có thể không phù hợp với sở thích của bạn, nhưng chúng được thiết kế đặc biệt để xử lý các chuỗi if-elif-elif-else, giống như OP yêu cầu. Họ không phải là khó để tìm hiểu và duyên dáng có thể xử lý tình huống mà không phải là tuân theo tra cứu từ điển logic: 'A' if grade>=90 else 'B' if grade>=80 else 'C' if grade>=70 else 'F'.
Raymond Hettinger

1
Nếu có một lợi thế của việc xác định dbên ngoài sự hiểu biết?
Chris_Rands

Lý do tôi thích đọc hiểu danh sách hơn là nó đọc giống như tiếng Anh. Ngay cả một người không phải lập trình viên cũng có thể hiểu nó làm gì. Với giải pháp này, bạn phải hiểu phương thức dict.get ().
Tim Skov Jacobsen

25

Bạn có thể, đại loại.

Lưu ý rằng khi bạn sử dụng sytax như:

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

Bạn đang sử dụng dạng bậc ba của toán tử if / else (nếu bạn quen thuộc với các ngôn ngữ như C, nó giống như ?:cấu trúc (v == 1 ? 'yes' : 'no'):).

Dạng bậc ba của toán tử if / else không tích hợp sẵn 'elif', nhưng bạn có thể mô phỏng nó trong điều kiện 'else':

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

Điều này giống như nói:

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

Vì vậy, không có cấu trúc 'elif' trực tiếp như bạn đã hỏi, nhưng nó có thể được mô phỏng bằng các câu lệnh if / else lồng nhau.


Đoạn mã cuối cùng là rất sâu sắc cảm ơn!
tà đạo

3

Có thể bạn muốn điều này:

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

print ([['idle','no','yes'][2*(n==1)+(n==2)] for n in l])

2

Bạn có thể sử dụng khả năng hiểu danh sách là bạn sẽ tạo một danh sách khác từ bản gốc.

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

Một cách dễ dàng khác là sử dụng khả năng hiểu danh sách có điều kiện như sau:

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

cung cấp cho bạn đúng anwer:

['có', 'không', 'nhàn rỗi', 'nhàn rỗi', 'nhàn rỗi']

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.