SORU
7 Ocak 2011, Cuma


Tek listeden çiftleri

Yeterince sık, çift tarafından bir listesi işlemek için ihtiyacı buldum. Pythonic ve verimli bir yol olacağını bunu merak ettim ve Google'da bunu buldum:

pairs = zip(t[::2], t[1::2])

Bu pythonic yeterli olduğunu düşündüm, ama yeni bir tartışma idioms versus efficiency, ayarlama yaptıktan sonra bazı testler yapmaya karar verdim:

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

Bu benim bilgisayarda şöyleydi:

1.48668909073 2.63187503815 1.14518594742
0.105381965637 1.35109519958 1.24571323395
0.00257992744446 1.46182489395 1.45924496651
0.00251388549805 1.70076990128 1.69825601578

Eğer onları doğru yorumlamak olursam, listeler, liste, dizin oluşturma ve liste uygulaması Python Dilimleme çok verimli olduğu anlamına gelir. Sonuç Her iki rahatlatıcı ve beklenmedik.

Orada başka, "" çiftleri bir listesini geçme yolu? daha iyi olur

Eğer liste elemanları tek bir sayı varsa o zaman son bir çiftleri olacak unutmayın.

Tüm elemanları dahil olduğundan emin olmak için doğru yolu olurdu?

Testlerin cevapları bu iki öneri ekledim:

def pairwise(t):
    it = iter(t)
    return izip(it, it)

def chunkwise(t, size=2):
    it = iter(t)
    return izip(*[it]*size)

Bu sonuçlar şunlardır:

0.00159502029419 1.25745987892 1.25586485863
0.00222492218018 1.23795199394 1.23572707176

Sonuçları şimdiye kadar

En pythonic ve çok etkili:

pairs = izip(t[::2], t[1::2])

En verimli ve çok pythonic:

pairs = izip(*[iter(t)]*2)

Bana ilk cevap ikinci bir tek kişi kullanırken iki kullanımına kullanan grok için bir an sürdü.

Uğraşmak dizileri ile bir tek sayı unsurları, öneri edilmiş olmasına orijinal sekansı eklemek bir öğe (None) bu olur ile eşleştirilmiş önceki son öğe, bir şey elde edilebilir itertools.izip_longest().

Nihayet

Unutmayın, Python 3'te.x, zip() itertools.izip() gibi davranır ve itertools.izip() gitti.

CEVAP
7 Ocak 2011, Cuma


20 ** ilk çözüm kolay okumak için, çünkü en iyi (ve Python, *21 3* otomatik olarak bir liste yerine bir yineleyici döndürür) olduğunu söyleyebilirim.

Tüm elemanları dahil olduğundan emin olmak için, sadece None listeyi uzatmak olabilir.

Eğer liste elemanları tek bir sayı varsa, o zaman, son çifti (item, None) olacak.

>>> t = [1,2,3,4,5]
>>> t.append(None)
>>> zip(t[::2], t[1::2])
[(1, 2), (3, 4), (5, None)]
>>> t = [1,2,3,4,5,6]
>>> t.append(None)
>>> zip(t[::2], t[1::2])
[(1, 2), (3, 4), (5, 6)]

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • LimeFire

    LimeFire

    2 ŞUBAT 2012
  • Matthew Smith

    Matthew Smit

    24 Mayıs 2010
  • Migs351

    Migs351

    3 HAZİRAN 2007