2912 votes

Comment vous répartissez vous une liste en morceaux de taille égale en Python?

J'ai une liste de longueur arbitraire, et j'ai besoin de la découper en morceaux de taille égale et les opérer sur elle. Il y a bien des façons de le faire, comme de garder un compteur et deux listes, et lors de la deuxième liste se remplit, l'ajouter à la première liste et vide la deuxième liste pour la prochaine série de données, mais c'est extrêmement cher.

Je me demandais si quelqu'un avait une solution à ce pour les listes de n'importe quelle longueur, par exemple à l'aide de générateurs.

Cela devrait fonctionner:

l = range(1, 1000)
print chunks(l, 10) -> [ [ 1..10 ], [ 11..20 ], .., [ 991..999 ] ]

Je cherchais quelque chose d'utile en itertools mais je ne pouvais pas trouver quelque chose évidemment utile. Pourrait avez manqué, cependant.

Liés à la question: qu'est-Ce que la plupart des "pythonic" chemin à parcourir une liste en morceaux?

4170voto

Ned Batchelder Points 128913

Voici un générateur qui produit les morceaux que vous voulez:

def chunks(l, n):
    """ Yield successive n-sized chunks from l.
    """
    for i in xrange(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]]

643voto

oremj Points 2684

Si vous voulez quelque chose de super simple:

def chunks(l, n):
    if n < 1:
        n = 1
    return [l[i:i + n] for i in range(0, len(l), n)]

339voto

tzot Points 32224

Directement à partir de la documentation Python (pour les recettes de itertools):

from itertools import izip, chain, repeat

def grouper(n, iterable, padvalue=None):
    "grouper(3, 'abcdefg', 'x') --> ('a','b','c'), ('d','e','f'), ('g','x','x')"
    return izip(*[chain(iterable, repeat(padvalue, n-1))]*n)

Un autre de prendre, comme l'a suggéré J. F. Sebastian:

from itertools import izip_longest

def grouper(n, iterable, padvalue=None):
    "grouper(3, 'abcdefg', 'x') --> ('a','b','c'), ('d','e','f'), ('g','x','x')"
    return izip_longest(*[iter(iterable)]*n, fillvalue=padvalue)

Je suppose que Guido est temps de fonctionnement de la machine-travaillé-fonctionnera-aura travaillé, avait repris le travail.

Ces solutions fonctionnent, car [iter(iterable)]*n (ou l'équivalent dans la version antérieure) crée un itérateur, répété n fois dans la liste. izip_longest puis exécute efficacement un round-robin de "chaque" iterator; parce que c'est la même itérateur, il est avancé par chacun de ces appels, résultant dans chacun de ces zip-roundrobin générer un n-uplet d' n articles.

118voto

Markus Jarderot Points 33893

Voici un générateur de travail sur l'arbitraire 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))

Exemple:

>>> 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]]

63voto

Tomasz Wysocki Points 4392
def chunk(input, size):
    return map(None, *([iter(input)] * size))

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X