Έχω μια λίστα αυθαίρετου μήκους και πρέπει να τη χωρίσω σε κομμάτια ίσου μεγέθους και να την επεξεργαστώ. Υπάρχουν κάποιοι προφανείς τρόποι για να το κάνω αυτό, όπως το να κρατάω έναν μετρητή και δύο λίστες, και όταν η δεύτερη λίστα γεμίζει, να την προσθέτω στην πρώτη λίστα και να αδειάζω τη δεύτερη λίστα για τον επόμενο γύρο δεδομένων, αλλά αυτό είναι δυνητικά εξαιρετικά δαπανηρό.
Αναρωτιόμουν αν κάποιος είχε μια καλή λύση για αυτό για λίστες οποιουδήποτε μήκους, π.χ. χρησιμοποιώντας γεννήτριες.
Έψαχνα για κάτι χρήσιμο στο itertools
αλλά δεν μπόρεσα να βρω κάτι προφανώς χρήσιμο. Μπορεί να μου ξέφυγε, όμως.
Σχετική ερώτηση: Ποιος είναι ο πιο "πυθωνικός" τρόπος για να επαναλάβετε μια λίστα σε κομμάτια;.
Ορίστε μια γεννήτρια που παράγει τα κομμάτια που θέλετε:
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]]
Αν χρησιμοποιείτε Python 2, θα πρέπει να χρησιμοποιήσετε την xrange()
αντί της range()
:
def chunks(l, n):
"""Yield successive n-sized chunks from l."""
for i in xrange(0, len(l), n):
yield l[i:i + n]
Επίσης, μπορείτε απλά να χρησιμοποιήσετε την κατανόηση λίστας αντί να γράψετε μια συνάρτηση, αν και είναι καλή ιδέα να ενθυλακώνετε λειτουργίες όπως αυτή σε ονομαστικές συναρτήσεις, ώστε ο κώδικάς σας να είναι ευκολότερα κατανοητός. Python 3:
[l[i:i + n] for i in range(0, len(l), n)]
Έκδοση Python 2:
[l[i:i + n] for i in xrange(0, len(l), n)]
Εδώ είναι μια γεννήτρια που δουλεύει σε αυθαίρετα iterables:
def split_seq(iterable, size):
it = iter(iterable)
item = list(itertools.islice(it, size))
while item:
yield item
item = list(itertools.islice(it, size))
Παράδειγμα:
>>> 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]]
Εάν γνωρίζετε το μέγεθος του καταλόγου:
def SplitList(mylist, chunk_size):
return [mylist[offs:offs+chunk_size] for offs in range(0, len(mylist), chunk_size)]
Αν δεν το ξέρετε (ένας επαναλήπτης):
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
Στην τελευταία περίπτωση, μπορεί να επαναδιατυπωθεί με έναν πιο όμορφο τρόπο αν μπορείτε να είστε σίγουροι ότι η ακολουθία περιέχει πάντα έναν ακέραιο αριθμό τεμαχίων δεδομένου μεγέθους (δηλαδή δεν υπάρχει ατελές τελευταίο τεμάχιο).