2011-10-01 47 views
7

Tôi có một danh sách và tôi muốn sử dụng một chức năng nhất định chỉ trên các mục của nó đáp ứng một điều kiện nhất định - để các mục nhập khác chưa được sửa đổi.Đọc danh sách Python - đơn giản

Ví dụ: Giả sử tôi muốn nhân với 2 chỉ những yếu tố đó.

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

kết quả Wanted:

a_list => [1, 4, 3, 8, 5] 

Nhưng [elem * 2 for elem in a_list if elem %2 == 0] sản lượng [4, 8] (nó đóng vai trò như một bộ lọc ngoài).

Cách chính xác để thực hiện điều đó là gì?

Trả lời

18

Sử dụng một conditional expression:

[x * 2 if x % 2 == 0 else x 
for x in a_list] 

(lưu ý Math đam mê của: bạn cũng có thể giải quyết trường hợp cụ thể này với

[x * (2 - x % 2) for x in a_list] 

nhưng tôi muốn các tùy chọn đầu tiên anyway;)

+0

Cảm ơn, điều này đã hiệu quả. Ngoài ra, cảm ơn bạn đã chỉnh sửa, tôi sẽ cố gắng sử dụng cùng một định dạng tiếp theo. –

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

print [elem*2 if elem%2==0 else elem for elem in a_list ] 

hoặc nếu bạn có danh sách rất dài mà bạn muốn sửa đổi tại chỗ:

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

for i,elem in enumerate(a_list): 
    if elem%2==0: 
     a_list[i] = elem*2 

như vậy, chỉ có các yếu tố thậm chí được sửa đổi

+0

Không nên 'a_list [:] = list_comprehension' hoạt động để thay thế tại chỗ? Và điều đó mà không cần phải lặp lại trong python? – Voo

+0

@agf Vì vậy, nó sẽ tạo danh sách mới ở một nơi khác và sau đó cập nhật các yếu tố? Quá tệ, tôi nghĩ vì những hạn chế của việc hiểu danh sách, chúng tôi có thể đảm bảo rằng một phần tử chỉ có thể được tham chiếu trước khi nó được ghi đè để có thể được tối ưu hóa. – Voo

+0

@Voo Phân bổ tại chỗ hoạt động từ bất kỳ lần lặp nào, do đó bạn có thể thực hiện nó từ biểu thức trình tạo thay thế. Tôi chỉ thử nó, và điều đó thực sự có vẻ hoạt động ngay cả khi bạn sử dụng 'reversed (a_list)' hoặc một trình tạo ra ít mục hơn độ dài của danh sách. Không phải thứ tôi đã từng nghĩ trước đây; cảm ơn vì đã đưa ra ý tưởng :). – agf

0

Bạn có thể sử dụng lambda:

>>> a_list = [1, 2, 3, 4, 5] 
>>> f = lambda x: x%2 and x or x*2 
>>> a_list = [f(i) for i in a_list] 
>>> a_list 
[1, 4, 3, 8, 5] 

Sửa - Suy nghĩ về nhận xét agf 's tôi đã thực hiện một phiên bản thứ 2 của mã của tôi:

>>> a_list = [1, 2, 3, 4, 5] 
>>> f = lambda x: x if x%2 else x*2 
>>> a_list = [f(i) for i in a_list] 
>>> a_list 
[1, 4, 3, 8, 5] 
+0

Không sử dụng 'điều kiện và giá trị true_value hoặc false_value' để mô phỏng hoạt động bậc ba; có một phiên bản thực sự trong Python. Ngoài ra, không cần phải quấn nó trong một lambda một trong hai cách, vì nó là một biểu thức chứ không phải là một tuyên bố nó hoạt động tốt ngay trong danh sách hiểu. 'lambda' có cùng giới hạn, do đó, có _never_ một nhu cầu cho một trong một biểu thức danh sách hoặc biểu thức máy phát. – agf

+0

@agf - Tôi hiểu (và đồng ý) nhận xét của bạn về lambda, nhưng trong trường hợp này có vẻ như tôi là một cách khác (mặc dù cách xa hoàn toàn) để đưa vào các cấp độ khác nhau về logic chọn mục từ danh sách hiểu . Và cảm ơn bạn về phần còn lại về toán tử ternary Python. Tôi đã thực hiện một phiên bản thứ 2 để phản ánh điều này. –

+0

'lambda x:' và 'f()' là 12 ký tự, '[cho i trong a_list]' là 18 - vì vậy bạn làm cho nó rõ ràng hơn và nhanh hơn bằng cách có biểu thức nội tuyến thay vì trong một 'lambda' cho chỉ có thêm sáu ký tự nếu bạn có toàn bộ danh sách đọc riêng biệt thay vì chỉ là một hàm mới. – agf

Các vấn đề liên quan