Cukup sering, saya merasa perlu memproses daftar secara berpasangan. Saya bertanya-tanya mana yang akan menjadi cara pythonic dan efisien untuk melakukannya, dan menemukan ini di Google:
pairs = zip(t[::2], t[1::2])
Saya pikir itu cukup pythonic, tetapi setelah diskusi baru-baru ini yang melibatkan idiom versus efisiensi , saya memutuskan untuk melakukan beberapa tes:
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
Ini adalah hasil di komputer saya:
1.48668909073 2.63187503815 1.14518594742
0.105381965637 1.35109519958 1.24571323395
0.00257992744446 1.46182489395 1.45924496651
0.00251388549805 1.70076990128 1.69825601578
Jika saya menafsirkannya dengan benar, itu berarti penerapan daftar, pengindeksan daftar, dan pemotongan daftar dengan Python sangat efisien. Hasilnya menghibur dan tidak terduga.
Apakah ada cara lain yang "lebih baik" untuk melintasi daftar secara berpasangan?
Perhatikan bahwa jika daftar memiliki jumlah elemen ganjil maka yang terakhir tidak akan ada di pasangan mana pun.
Cara manakah yang benar untuk memastikan bahwa semua elemen disertakan?
Saya menambahkan dua saran ini dari jawaban tes:
def pairwise(t):
it = iter(t)
return izip(it, it)
def chunkwise(t, size=2):
it = iter(t)
return izip(*[it]*size)
Inilah hasilnya:
0.00159502029419 1.25745987892 1.25586485863
0.00222492218018 1.23795199394 1.23572707176
Hasil sejauh ini
Paling pythonic dan sangat efisien:
pairs = izip(t[::2], t[1::2])
Paling efisien dan sangat pythonic:
pairs = izip(*[iter(t)]*2)
Butuh beberapa saat bagi saya untuk menjelaskan bahwa jawaban pertama menggunakan dua iterator sedangkan yang kedua menggunakan satu satu.
Untuk menangani urutan dengan jumlah elemen ganjil, sarannya adalah menambah urutan asli dengan menambahkan satu elemen ( None
) yang dipasangkan dengan elemen terakhir sebelumnya, sesuatu yang dapat dicapai dengan itertools.izip_longest()
.
Akhirnya
Perhatikan bahwa, dalam Python 3.x, zip()
berperilaku sebagai itertools.izip()
, dan itertools.izip()
hilang.