Hiểu danh sách một dòng: các biến thể if-other


178

Đó là nhiều hơn về cú pháp hiểu danh sách python. Tôi đã có một sự hiểu biết danh sách tạo ra danh sách các số lẻ của một phạm vi nhất định:

[x for x in range(1, 10) if x % 2]

Điều này tạo bộ lọc - Tôi đã có một danh sách nguồn, nơi tôi xóa các số chẵn ( if x % 2). Tôi muốn sử dụng một cái gì đó như nếu-thì-khác ở đây. Mã sau không thành công:

>>> [x for x in range(1, 10) if x % 2 else x * 100]
  File "<stdin>", line 1
    [x for x in range(1, 10) if x % 2 else x * 100]
                                         ^
SyntaxError: invalid syntax

Có một biểu thức python như if-other:

1 if 0 is 0 else 3

Làm thế nào để sử dụng nó trong một danh sách hiểu?


1
Cho những gì nó có giá trị, bạn có một "danh sách hiểu", không phải là một trình tạo. Cú pháp cuối cùng là giống nhau ngoại trừ việc các trình tạo sử dụng ()thay vì [].
mgilson


2
Tôi phải mất một thời gian để hiểu tại sao if x % 2 loại bỏ các số chẵn (thay vì giữ chúng) - đó là bởi vì khi nào xthì x % 2biểu thức sẽ dẫn đến 0, trong đó, lần lượt, đánh giá False, trong khi bất kỳ intngoại trừ 0đánh giá True.

Câu trả lời:


328

x if y else zlà cú pháp cho biểu thức bạn trả về cho mỗi phần tử. Vì vậy, bạn cần:

[ x if x%2 else x*100 for x in range(1, 10) ]

Sự nhầm lẫn xuất phát từ thực tế bạn đang sử dụng bộ lọc trong ví dụ đầu tiên, nhưng không phải trong lần thứ hai. Trong ví dụ thứ hai, bạn chỉ ánh xạ từng giá trị sang giá trị khác, sử dụng biểu thức toán tử ternary.

Với bộ lọc, bạn cần:

[ EXP for x in seq if COND ]

Không có bộ lọc bạn cần:

[ EXP for x in seq ]

và trong ví dụ thứ hai của bạn, biểu thức là một "phức tạp", điều này xảy ra liên quan đến một if-else.


2
Tôi có một câu hỏi ... [x for x in range(1, 10) if x % 2]là cú pháp đúng. [x if x % 2 for x in range(1, 10)]- đây không phải là, nhưng [x if x%2 else x*100 for x in range(1, 10)]một lần nữa, đúng cú pháp. Làm thế nào mà?
ducin

@tkoomzaaskz trong ví dụ thứ hai của bạn, đây không phải là toán tử ternary-if-other (thiếu else), cũng không phải là bộ lọc (vì nó nằm trong EXPphần hiểu danh sách)
shx2

3
@tkoomzaaskz Để làm rõ hơn, lưu ý rằng bạn có thể thêm một giây ifở cuối: [x if x%2 else x*100 for x in range(1, 10) if not x%3]Đầu tiên iflà một phần của toán tử ternary, thứ hai iflà một phần của cú pháp hiểu danh sách. Toàn bộ x if x%2 else x*100là "trên cùng một cấp độ" là một đơn giản 2*x, đó là biểu thức để đánh giá ở phía bên trái của for, khi quá trình lọc if not x%3đã diễn ra.
zx81

Xin chào, liệu một câu lệnh một dòng có hiệu quả hơn so với thực hiện trên hai dòng như thế for i in x:và sau đó trong vòng lặp for if i == y:?
Alexis.Rolland


12

Bạn cũng có thể làm điều đó với việc hiểu danh sách:

A=[[x*100, x][x % 2 != 0] for x in range(1,11)]
print A

1
Rất đẹp. Một lát boolean. Cảm ơn bạn chỉ cho tôi một giải pháp dễ đọc hơn.

Bạn cũng có thể gán gấp đôi như vậy: A, B = [10,11] [a == 19], [1,14] [a == 20]
Stefan Gruenwald

10

Chỉ là một giải pháp khác, hy vọng ai đó có thể thích nó:

Sử dụng: [Sai, Đúng] [Biểu hiện]

>>> map(lambda x: [x*100, x][x % 2 != 0], range(1,10))
[1, 200, 3, 400, 5, 600, 7, 800, 9]
>>>

3

Tôi đã có thể làm điều này

>>> [x if x % 2 != 0 else x * 100 for x in range(1,10)]
    [1, 200, 3, 400, 5, 600, 7, 800, 9]
>>>
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.