Thông thường, tôi thấy cần phải xử lý danh sách theo từng cặp. Tôi đang băn khoăn không biết đâu sẽ là cách hiệu quả và tốt để làm điều đó, và tìm thấy điều này trên Google:
pairs = zip(t[::2], t[1::2])
Tôi nghĩ rằng điều đó đã đủ khó hiểu, nhưng sau một cuộc thảo luận gần đây liên quan đến thành ngữ và hiệu quả , tôi quyết định thực hiện một số thử nghiệm:
import time
from itertools import islice, izip
def pairs_1(t):
return zip(t[::2], t[1::2])
def pairs_2(t):
return izip(t[::2], t[1::2])
def pairs_3(t):
return izip(islice(t,None,None,2), islice(t,1,None,2))
A = range(10000)
B = xrange(len(A))
def pairs_4(t):
# ignore value of t!
t = B
return izip(islice(t,None,None,2), islice(t,1,None,2))
for f in pairs_1, pairs_2, pairs_3, pairs_4:
# time the pairing
s = time.time()
for i in range(1000):
p = f(A)
t1 = time.time() - s
# time using the pairs
s = time.time()
for i in range(1000):
p = f(A)
for a, b in p:
pass
t2 = time.time() - s
print t1, t2, t2-t1
Đây là kết quả trên máy tính của tôi:
1.48668909073 2.63187503815 1.14518594742
0.105381965637 1.35109519958 1.24571323395
0.00257992744446 1.46182489395 1.45924496651
0.00251388549805 1.70076990128 1.69825601578
Nếu tôi diễn giải chúng một cách chính xác, điều đó có nghĩa là việc triển khai danh sách, lập chỉ mục danh sách và phân loại danh sách trong Python rất hiệu quả. Đó là một kết quả vừa an ủi vừa bất ngờ.
Có cách nào khác "tốt hơn" để duyệt danh sách theo cặp không?
Lưu ý rằng nếu danh sách có một số phần tử lẻ thì phần tử cuối cùng sẽ không nằm trong bất kỳ cặp nào.
Cách nào sẽ là cách phù hợp để đảm bảo rằng tất cả các yếu tố đều được bao gồm?
Tôi đã thêm hai gợi ý này từ câu trả lời cho các bài kiểm tra:
def pairwise(t):
it = iter(t)
return izip(it, it)
def chunkwise(t, size=2):
it = iter(t)
return izip(*[it]*size)
Đây là những kết quả:
0.00159502029419 1.25745987892 1.25586485863
0.00222492218018 1.23795199394 1.23572707176
Kết quả cho đến nay
Hầu hết pythonic và rất hiệu quả:
pairs = izip(t[::2], t[1::2])
Hiệu quả nhất và rất hiệu quả:
pairs = izip(*[iter(t)]*2)
Tôi mất một lúc để tìm hiểu rằng câu trả lời đầu tiên sử dụng hai trình vòng lặp trong khi câu trả lời thứ hai sử dụng một trình vòng lặp duy nhất.
Để đối phó với các chuỗi có số phần tử lẻ, đề xuất là tăng chuỗi ban đầu bằng cách thêm một phần tử ( None
) được ghép nối với phần tử cuối cùng trước đó, một cái gì đó có thể đạt được itertools.izip_longest()
.
Cuối cùng
Lưu ý rằng, trong Python 3.x, zip()
hoạt động như itertools.izip()
và itertools.izip()
không còn nữa.
timeit
mô-đun.