Các giải pháp cho đến bây giờ chỉ giải quyết các danh sách, và hầu hết là sao chép danh sách. Theo kinh nghiệm của tôi, rất nhiều lần điều đó là không thể.
Ngoài ra, họ không đối phó với thực tế là bạn có thể có các phần tử lặp lại trong danh sách.
Tiêu đề câu hỏi của bạn cho biết " Giá trị trước đó và giá trị tiếp theo bên trong vòng lặp ", nhưng nếu bạn chạy hầu hết các câu trả lời ở đây bên trong một vòng lặp, bạn sẽ phải lặp lại toàn bộ danh sách trên mỗi phần tử để tìm nó.
Vì vậy, tôi vừa tạo một hàm đó. bằng cách sử dụng itertools
mô-đun, tách và cắt phần có thể lặp lại, đồng thời tạo các bộ giá trị với các phần tử trước và sau cùng nhau. Không chính xác mã của bạn làm gì, nhưng nó đáng để xem, vì nó có thể giải quyết vấn đề của bạn.
from itertools import tee, islice, chain, izip
def previous_and_next(some_iterable):
prevs, items, nexts = tee(some_iterable, 3)
prevs = chain([None], prevs)
nexts = chain(islice(nexts, 1, None), [None])
return izip(prevs, items, nexts)
Sau đó, sử dụng nó trong một vòng lặp và bạn sẽ có các mục trước đó và tiếp theo trong đó:
mylist = ['banana', 'orange', 'apple', 'kiwi', 'tomato']
for previous, item, nxt in previous_and_next(mylist):
print "Item is now", item, "next is", nxt, "previous is", previous
Kết quả:
Item is now banana next is orange previous is None
Item is now orange next is apple previous is banana
Item is now apple next is kiwi previous is orange
Item is now kiwi next is tomato previous is apple
Item is now tomato next is None previous is kiwi
Nó sẽ hoạt động với bất kỳ danh sách kích thước nào (vì nó không sao chép danh sách) và với bất kỳ danh sách có thể lặp lại nào (tệp, bộ, v.v.). Bằng cách này, bạn chỉ có thể lặp lại chuỗi và có sẵn các mục trước đó và tiếp theo bên trong vòng lặp. Không cần phải tìm kiếm lại mục trong chuỗi.
Giải thích ngắn gọn về mã:
tee
được sử dụng để tạo hiệu quả 3 trình vòng lặp độc lập trên chuỗi đầu vào
chain
liên kết hai chuỗi thành một; nó được sử dụng ở đây để nối chuỗi một phần tử [None]
vàoprevs
islice
được sử dụng để tạo một chuỗi tất cả các phần tử ngoại trừ phần tử đầu tiên, sau đó chain
được sử dụng để nối a None
vào cuối
- Bây giờ có 3 trình tự độc lập dựa trên
some_iterable
đó trông giống như:
prevs
: None, A, B, C, D, E
items
: A, B, C, D, E
nexts
: B, C, D, E, None
- cuối cùng
izip
được sử dụng để thay đổi 3 trình tự thành một trình tự bộ ba.
Lưu ý rằng izip
dừng khi bất kỳ chuỗi đầu vào nào hết, vì vậy phần tử cuối cùng của prevs
sẽ bị bỏ qua, điều này đúng - không có phần tử nào mà phần tử cuối cùng là của nó prev
. Chúng tôi có thể cố gắng loại bỏ các yếu tố cuối cùng khỏi prevs
nhưng izip
hành vi của nó khiến điều đó trở nên thừa
Cũng lưu ý rằng tee
, izip
, islice
và chain
đến từ các itertools
mô-đun; chúng hoạt động trên các trình tự đầu vào của họ một cách nhanh chóng (một cách lười biếng), điều này làm cho chúng hoạt động hiệu quả và không dẫn đến nhu cầu phải có toàn bộ chuỗi trong bộ nhớ cùng một lúc.
Trong python 3
, nó sẽ hiển thị một lỗi trong khi nhập izip
, bạn có thể sử dụng zip
thay thế izip
. Không cần nhập zip
, nó được xác định trước trong python 3
- nguồn