Minulla on mielivaltaisen pituinen lista, ja minun on jaettava se samankokoisiin palasiin ja operoitava sillä. On olemassa joitakin ilmeisiä tapoja tehdä tämä, kuten laskurin ja kahden listan pitäminen, ja kun toinen lista täyttyy, se lisätään ensimmäiseen listaan ja tyhjennetään toinen lista seuraavaa datakierrosta varten, mutta tämä on mahdollisesti erittäin kallista.
Mietin, olisiko kenelläkään hyvää ratkaisua tähän minkä tahansa pituisille listoille, esimerkiksi käyttämällä generaattoreita.
Etsin jotain hyödyllistä itertools
-ohjelmasta, mutta en löytänyt mitään ilmeisen hyödyllistä. Saattaa kuitenkin jäädä huomaamatta.
Aiheeseen liittyvä kysymys: Mikä on "pythonisin" tapa iteroida listan yli kappaleittain?[1][2].
Tässä on generaattori, joka tuottaa haluamasi palaset:
def chunks(l, n):
"""Yield successive n-sized chunks from l."""
for i in range(0, len(l), n):
yield l[i:i + n]
import pprint
pprint.pprint(list(chunks(range(10, 75), 10)))
[[10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
[20, 21, 22, 23, 24, 25, 26, 27, 28, 29],
[30, 31, 32, 33, 34, 35, 36, 37, 38, 39],
[40, 41, 42, 43, 44, 45, 46, 47, 48, 49],
[50, 51, 52, 53, 54, 55, 56, 57, 58, 59],
[60, 61, 62, 63, 64, 65, 66, 67, 68, 69],
[70, 71, 72, 73, 74]]
Jos käytät Python 2:ta, sinun tulisi käyttää xrange()
:n sijasta xrange()
:
def chunks(l, n):
"""Yield successive n-sized chunks from l."""
for i in xrange(0, len(l), n):
yield l[i:i + n]
Voit myös yksinkertaisesti käyttää listan ymmärtämistä funktion kirjoittamisen sijasta, vaikka onkin hyvä idea kapseloida tällaiset operaatiot nimettyihin funktioihin, jotta koodisi on helpompi ymmärtää. Python 3:
[l[i:i + n] for i in range(0, len(l), n)]
Python 2 -versio:
[l[i:i + n] for i in xrange(0, len(l), n)]
Tässä on generaattori, joka toimii mielivaltaisille iterableille:
def split_seq(iterable, size):
it = iter(iterable)
item = list(itertools.islice(it, size))
while item:
yield item
item = list(itertools.islice(it, size))
Esimerkki:
>>> import pprint
>>> pprint.pprint(list(split_seq(xrange(75), 10)))
[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
[20, 21, 22, 23, 24, 25, 26, 27, 28, 29],
[30, 31, 32, 33, 34, 35, 36, 37, 38, 39],
[40, 41, 42, 43, 44, 45, 46, 47, 48, 49],
[50, 51, 52, 53, 54, 55, 56, 57, 58, 59],
[60, 61, 62, 63, 64, 65, 66, 67, 68, 69],
[70, 71, 72, 73, 74]]
Jos tiedät luettelon koon:
def SplitList(mylist, chunk_size):
return [mylist[offs:offs+chunk_size] for offs in range(0, len(mylist), chunk_size)]
Jos et tiedä (iteraattori):
def IterChunks(sequence, chunk_size):
res = []
for item in sequence:
res.append(item)
if len(res) >= chunk_size:
yield res
res = []
if res:
yield res # yield the last, incomplete, portion
Jälkimmäisessä tapauksessa se voidaan muotoilla kauniimmin uudelleen, jos voidaan olla varmoja siitä, että sekvenssi sisältää aina kokonaisen määrän tietyn kokoisia kappaleita (eli ei ole epätäydellistä viimeistä kappaletta).