2011-12-17 53 views
8

những gì tôi về cơ bản cần là kiểm tra mọi thành phần của danh sách và nếu một số tiêu chí phù hợp, tôi muốn xóa nó khỏi danh sách.cách sửa đổi chính xác vòng lặp của vòng lặp trong python từ bên trong vòng lặp

Vì vậy, ví dụ chúng ta hãy nói rằng

list = [ 'a', 'b', 'c', 'd', 'e']

tôi về cơ bản muốn viết (trong nguyên lý và không phải mã thực tế mà tôi cố gắng triển khai)

Nếu một phần tử của danh sách là 'b' hoặc 'c', hãy xóa nó khỏi danh sách và thực hiện bước tiếp theo.

Nhưng

for s in list: 
    if s=='b' or s=='c': 
     list.remove(s) 

thất bại bởi vì khi 'B' được lấy ra vòng lặp mất 'd' và không phải là 'c' là yếu tố tiếp theo. Vì vậy, có một cách để làm điều đó nhanh hơn so với lưu trữ các yếu tố trong một danh sách riêng biệt và loại bỏ chúng sau đó?

Cảm ơn.

Trả lời

9

Cách dễ dàng hơn là sử dụng một bản sao của danh sách - nó có thể được thực hiện với một lát mà kéo dài "từ đầu" đến "kết thúc" của danh sách, như thế này:

for s in list[:]: 
    if s=='b' or s=='c': 
     list.remove(s) 

Bạn đã xem xét điều này, và điều này là đơn giản, đủ để được trong mã của bạn, trừ khi danh sách này là thực sự lớn, và trong một phần quan trọng của mã (như, trong vòng lặp chính của một trò chơi hành động). Trong trường hợp đó, đôi khi tôi sử dụng các thành ngữ sau:

to_remove = [] 
for index, s in enumerate(list): 
    if s == "b" or s == "c": 
     to_remove.append(index) 

for index in reversed(to_remove): 
    del list[index] 

Tất nhiên bạn có thể dùng đến một vòng lặp while thay vì:

index = 0 
while index < len(list): 
    if s == "b" or s == "c": 
     del list[index] 
     continue 
    index += 1 
+0

jsbueno thank you very much. Tôi cảm thấy hơi xấu hổ vì không nghĩ vậy. Cảm ơn một lần nữa! – tst

+0

Tôi thực sự muốn một vòng lặp trong vòng lặp và ví dụ cuối cùng của bạn là hoàn hảo. cảm ơn một lần nữa. – tst

1

Nếu bạn là ok với việc tạo ra một bản sao của danh sách mà bạn có thể làm nó như thế này (list comprehension):

[s for s in list if s != 'b' and s != 'c'] 
8

Tốt hơn là không tái tạo lại những thứ đã có sẵn. Sử dụng các hàm filter và lambda trong các trường hợp này. Của nó nhiều hơn pythonic và trông sạch hơn.

filter(lambda x:x not in ['b','c'],['a','b','c','d','e']) 

cách khác bạn có thể sử dụng danh sách hiểu

[x for x in ['a','b','c','d','e'] if x not in ['b','c']] 
+0

Thực ra, việc hiểu danh sách trong ví dụ thứ hai của bạn là "nhiều Pythonic" hơn so với kết hợp bộ lọc và lambda. – jsbueno

+0

cảm ơn nhưng tôi cần phải đặt một vòng lặp như vậy vào một cách khác và cách này mọi thứ có thể trở nên thực sự lộn xộn. – tst

3

Đây chính là điều itertools.ifilter được thiết kế cho.

from itertools import ifilter 

ifilter(lambda x: x not in ['b', 'c'], ['a', 'b', 'c', 'd', 'e']) 

sẽ trả lại máy phát cho danh sách của bạn. Nếu bạn thực sự cần một danh sách, bạn có thể tạo ra nó bằng một trong những kỹ thuật tiêu chuẩn để chuyển đổi một máy phát điện vào một danh sách:

list(ifilter(lambda x: x not in ['b', 'c'], ['a', 'b', 'c', 'd', 'e'])) 

hoặc

[x for x in ifilter(lambda x: x not in ['b', 'c'], ['a', 'b', 'c', 'd', 'e'])] 
Các vấn đề liên quan