Fractionnement d'une liste en N parties de longueur approximativement égale

150

Quelle est la meilleure façon de diviser une liste en parties à peu près égales? Par exemple, si la liste a 7 éléments et est divisée en 2 parties, nous voulons obtenir 3 éléments dans une partie, et l'autre doit avoir 4 éléments.

Je cherche quelque chose comme even_split(L, n)ça qui se brise Len plusieurs nparties.

def chunks(L, n):
    """ Yield successive n-sized chunks from L.
    """
    for i in range(0, len(L), n):
        yield L[i:i+n]

Le code ci-dessus donne des morceaux de 3, plutôt que 3 morceaux. Je pourrais simplement transposer (itérer sur ceci et prendre le premier élément de chaque colonne, appeler cette première partie, puis prendre la seconde et la mettre dans la deuxième partie, etc.), mais cela détruit l'ordre des éléments.

wim
la source

Réponses:

64

Ce code est cassé en raison d'erreurs d'arrondi. Ne l'utilise pas!!!

assert len(chunkIt([1,2,3], 10)) == 10  # fails

En voici un qui pourrait fonctionner:

def chunkIt(seq, num):
    avg = len(seq) / float(num)
    out = []
    last = 0.0

    while last < len(seq):
        out.append(seq[int(last):int(last + avg)])
        last += avg

    return out

Essai:

>>> chunkIt(range(10), 3)
[[0, 1, 2], [3, 4, 5], [6, 7, 8, 9]]
>>> chunkIt(range(11), 3)
[[0, 1, 2], [3, 4, 5, 6], [7, 8, 9, 10]]
>>> chunkIt(range(12), 3)
[[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]]
Max Shawabkeh
la source
9
Votre exemple ne fonctionnera pas pour >>> chunkIt(range(8), 6)=>[[0], [1], [2, 3], [4], [5], [6], [7]]
nopper
1
@nopper, j'ai ajouté un conditionnel "if num == 1:" pour gérer ce cas de bord.
paulie4
24
Nouveaux visiteurs: veuillez ne pas utiliser ou voter pour ce code , il est cassé. par exemple, chunkIt(range(10), 9)devrait renvoyer 9 parties, mais ce n'est pas le cas.
wim
3
Ce fil de commentaires est vraiment déroutant car la réponse a été modifiée plusieurs fois. est-ce une bonne réponse? Pas une bonne réponse?
conchoecia
6
@conchoecia Pas une bonne réponse, continuez à faire défiler vers le bas. Cela n'a été modifié qu'une seule fois jusqu'à présent, et ce n'était qu'une modification triviale (le retrait de 2 espaces a été remplacé par 4). Malheureusement, l'OP "user248237dfsf" n'a pas été vu sur le site depuis plus de 3 ans, il y a donc peu d'espoir de changer la réponse acceptée.
wim
183

Vous pouvez l'écrire assez simplement sous forme de générateur de liste:

def split(a, n):
    k, m = divmod(len(a), n)
    return (a[i * k + min(i, m):(i + 1) * k + min(i + 1, m)] for i in range(n))

Exemple:

>>> list(split(range(11), 3))
[[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10]]
tixxit
la source
Insérer n = min(n, len(a)) # don't create empty bucketssur la ligne 1 pour éviter de créer des seaux vides dans des scénarios comme list(split(range(X, Y)))whereX < Y
abanana
Étant donné que je ne peux pas modifier mon commentaire - je dois ajouter que mon amendement précédent pourrait éventuellement augmenter une division par zéro erreur si la liste est vide, ce qui doit être contrôlé en externe ou ajouté à la solution.
abanana
4
Sur N réponse sur SO, c'est le seul qui a passé tous mes tests. gj!
avishayp
2
stackoverflow.com/a/37414115/210971 utilise la même méthode, mais fonctionne également pour une liste vide et un compteur fractionné 0.
LookAheadAtYourTypes
Belle! De plus, n peut être amené à fonctionner comme batch_size en échangeant k et n dans l'instruction return :)
haraprasadj
162

C'est la raison d'être de numpy.array_split*:

>>> import numpy as np
>>> print(*np.array_split(range(10), 3))
[0 1 2 3] [4 5 6] [7 8 9]
>>> print(*np.array_split(range(10), 4))
[0 1 2] [3 4 5] [6 7] [8 9]
>>> print(*np.array_split(range(10), 5))
[0 1] [2 3] [4 5] [6 7] [8 9]

* crédit à Zero Piraeus dans la chambre 6

wim
la source
1
Quel est le *dans printpour?
yuqli
2
Hey @yuqli, Il convertit une liste de quelque chose en arguments individuels en une fonction. essayez print(L)et `print (* L). Voir également stackoverflow.com/a/36908/2184122 ou recherchez "python use of asterisk".
Robert Lugg
121

Tant que vous ne voulez rien de stupide comme des morceaux continus:

>>> def chunkify(lst,n):
...     return [lst[i::n] for i in xrange(n)]
... 
>>> chunkify(range(13), 3)
[[0, 3, 6, 9, 12], [1, 4, 7, 10], [2, 5, 8, 11]]
emploi
la source
14
Je ne dirais pas que les morceaux continus sont idiots. Peut-être aimeriez-vous garder les morceaux triés (c.-à-d. Morceau [0] <morceau [1]), par exemple.
tixxit le
1
Je plaisantais. Mais si vous ne vous en souciez vraiment pas, la compréhension de la liste est agréable et concise.
emploi du
3
C'est un indice avec une foulée de n
smci
8
l'envoi de cette sortie dans 'zip' vous donne votre liste ordonnée: zip(*chunkify(range(13), 3))résultats[(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11)]
gens
2
Cette solution fonctionne bien, jusqu'à ce que vous ayez besoin de l'ordre de la liste.
s7anley
18

Changer le code pour produire des nmorceaux plutôt que des morceaux de n:

def chunks(l, n):
    """ Yield n successive chunks from l.
    """
    newn = int(len(l) / n)
    for i in xrange(0, n-1):
        yield l[i*newn:i*newn+newn]
    yield l[n*newn-newn:]

l = range(56)
three_chunks = chunks (l, 3)
print three_chunks.next()
print three_chunks.next()
print three_chunks.next()

qui donne:

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

Cela attribuera les éléments supplémentaires au groupe final qui n'est pas parfait mais qui correspond bien à votre spécification de "à peu près N parties égales" :-) Par là, je veux dire que 56 éléments seraient mieux comme (19,19,18) alors que cela donne (18, 18, 20).

Vous pouvez obtenir la sortie la plus équilibrée avec le code suivant:

#!/usr/bin/python
def chunks(l, n):
    """ Yield n successive chunks from l.
    """
    newn = int(1.0 * len(l) / n + 0.5)
    for i in xrange(0, n-1):
        yield l[i*newn:i*newn+newn]
    yield l[n*newn-newn:]

l = range(56)
three_chunks = chunks (l, 3)
print three_chunks.next()
print three_chunks.next()
print three_chunks.next()

qui sort:

[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]
paxdiablo
la source
cela me donne un résultat étrange. for p in chunks (range (54), 3): print len ​​(p) returns 18, 18, 51 ...
Corrigé, c'était le rendement final.
paxdiablo
voir aussi une solition au lien
Jakob Kroeker
C'est la réponse la plus utile pour des considérations pratiques. Merci!
mVChr
Quand j'utilise ceci, en faisant for x in chunks(mylist,num): print x, j'obtiens les morceaux désirés, mais entre eux j'obtiens une liste vide. Une idée pourquoi? Autrement dit, j'en reçois beaucoup [], un après chaque morceau.
synaptik
12

Si vous divisez des néléments en gros kmorceaux, vous pouvez rendre les n % kmorceaux d'un élément plus gros que les autres morceaux pour distribuer les éléments supplémentaires.

Le code suivant vous donnera la longueur des morceaux:

[(n // k) + (1 if i < (n % k) else 0) for i in range(k)]

Exemple: n=11, k=3résulte en[4, 4, 3]

Vous pouvez ensuite calculer facilement les indications de départ pour les morceaux:

[i * (n // k) + min(i, n % k) for i in range(k)]

Exemple: n=11, k=3résulte en[0, 4, 8]

En utilisant le i+1e morceau comme limite, nous obtenons que le ie morceau de liste lavec len nest

l[i * (n // k) + min(i, n % k):(i+1) * (n // k) + min(i+1, n % k)]

En dernière étape, créez une liste de tous les morceaux en utilisant la compréhension de liste:

[l[i * (n // k) + min(i, n % k):(i+1) * (n // k) + min(i+1, n % k)] for i in range(k)]

Exemple: n=11, k=3, l=range(n)résulte en[range(0, 4), range(4, 8), range(8, 11)]

MaPePeR
la source
6

Cela fera la division par une seule expression:

>>> myList = range(18)
>>> parts = 5
>>> [myList[(i*len(myList))//parts:((i+1)*len(myList))//parts] for i in range(parts)]
[[0, 1, 2], [3, 4, 5, 6], [7, 8, 9], [10, 11, 12, 13], [14, 15, 16, 17]]

La liste de cet exemple a la taille 18 et est divisée en 5 parties. La taille des pièces ne diffère que dans un seul élément.

bitagores
la source
6

Voir more_itertools.divide:

n = 2

[list(x) for x in mit.divide(n, range(5, 11))]
# [[5, 6, 7], [8, 9, 10]]

[list(x) for x in mit.divide(n, range(5, 12))]
# [[5, 6, 7, 8], [9, 10, 11]]

Installez via > pip install more_itertools.

pylang
la source
4

En voici un qui ajoute Nonepour rendre les listes de longueur égale

>>> from itertools import izip_longest
>>> def chunks(l, n):
    """ Yield n successive chunks from l. Pads extra spaces with None
    """
    return list(zip(*izip_longest(*[iter(l)]*n)))

>>> l=range(54)

>>> chunks(l,3)
[(0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51), (1, 4, 7, 10, 13, 16, 19, 22, 25, 28, 31, 34, 37, 40, 43, 46, 49, 52), (2, 5, 8, 11, 14, 17, 20, 23, 26, 29, 32, 35, 38, 41, 44, 47, 50, 53)]

>>> chunks(l,4)
[(0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52), (1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53), (2, 6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46, 50, None), (3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47, 51, None)]

>>> chunks(l,5)
[(0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50), (1, 6, 11, 16, 21, 26, 31, 36, 41, 46, 51), (2, 7, 12, 17, 22, 27, 32, 37, 42, 47, 52), (3, 8, 13, 18, 23, 28, 33, 38, 43, 48, 53), (4, 9, 14, 19, 24, 29, 34, 39, 44, 49, None)]
John La Rooy
la source
4

Voici ma solution:

def chunks(l, amount):
    if amount < 1:
        raise ValueError('amount must be positive integer')
    chunk_len = len(l) // amount
    leap_parts = len(l) % amount
    remainder = amount // 2  # make it symmetrical
    i = 0
    while i < len(l):
        remainder += leap_parts
        end_index = i + chunk_len
        if remainder >= amount:
            remainder -= amount
            end_index += 1
        yield l[i:end_index]
        i = end_index

Produit

    >>> list(chunks([1, 2, 3, 4, 5, 6, 7], 3))
    [[1, 2], [3, 4, 5], [6, 7]]
leotrubach
la source
4

Voici un générateur qui peut gérer n'importe quel nombre positif (entier) de blocs. Si le nombre de morceaux est supérieur à la longueur de la liste d'entrée, certains morceaux seront vides. Cet algorithme alterne entre les morceaux courts et longs plutôt que de les séparer.

J'ai également inclus du code pour tester la ragged_chunksfonction.

''' Split a list into "ragged" chunks

    The size of each chunk is either the floor or ceiling of len(seq) / chunks

    chunks can be > len(seq), in which case there will be empty chunks

    Written by PM 2Ring 2017.03.30
'''

def ragged_chunks(seq, chunks):
    size = len(seq)
    start = 0
    for i in range(1, chunks + 1):
        stop = i * size // chunks
        yield seq[start:stop]
        start = stop

# test

def test_ragged_chunks(maxsize):
    for size in range(0, maxsize):
        seq = list(range(size))
        for chunks in range(1, size + 1):
            minwidth = size // chunks
            #ceiling division
            maxwidth = -(-size // chunks)
            a = list(ragged_chunks(seq, chunks))
            sizes = [len(u) for u in a]
            deltas = all(minwidth <= u <= maxwidth for u in sizes)
            assert all((sum(a, []) == seq, sum(sizes) == size, deltas))
    return True

if test_ragged_chunks(100):
    print('ok')

Nous pouvons rendre cela légèrement plus efficace en exportant la multiplication dans l' rangeappel, mais je pense que la version précédente est plus lisible (et DRYer).

def ragged_chunks(seq, chunks):
    size = len(seq)
    start = 0
    for i in range(size, size * chunks + 1, size):
        stop = i // chunks
        yield seq[start:stop]
        start = stop
PM 2Bague
la source
3

Jetez un œil à numpy.split :

>>> a = numpy.array([1,2,3,4])
>>> numpy.split(a, 2)
[array([1, 2]), array([3, 4])]
dalloliogm
la source
5
Et numpy.array_split () est encore plus adéquate car elle se divise grossièrement.
Yariv
11
Cela ne fonctionne pas si la taille du tableau n'est pas divisible par le nombre de divisions.
Dan
1
C'est une mauvaise réponse, votre solution renvoie la liste des ndarrays, pas la liste des listes
Chłop Z Lasu
3

Implémentation à l'aide de la méthode numpy.linspace.

Spécifiez simplement le nombre de parties dans lesquelles vous voulez que le tableau soit divisé. Les divisions seront de taille presque égale.

Exemple :

import numpy as np   
a=np.arange(10)
print "Input array:",a 
parts=3
i=np.linspace(np.min(a),np.max(a)+1,parts+1)
i=np.array(i,dtype='uint16') # Indices should be floats
split_arr=[]
for ind in range(i.size-1):
    split_arr.append(a[i[ind]:i[ind+1]]
print "Array split in to %d parts : "%(parts),split_arr

Donne:

Input array: [0 1 2 3 4 5 6 7 8 9]
Array split in to 3 parts :  [array([0, 1, 2]), array([3, 4, 5]), array([6, 7, 8, 9])]
amit12690
la source
3

Ma solution, facile à comprendre

def split_list(lst, n):
    splitted = []
    for i in reversed(range(1, n + 1)):
        split_point = len(lst)//i
        splitted.append(lst[:split_point])
        lst = lst[split_point:]
    return splitted

Et le plus court one-liner sur cette page (écrit par ma fille)

def split(l, n):
    return [l[int(i*len(l)/n):int((i+1)*len(l)/n-1)] for i in range(n)]
Chłop Z Lasu
la source
FYI: Votre one-liner est cassé, donne de mauvais résultats. L'autre fonctionne à merveille.
Paulo Freitas
2

Utilisation de la compréhension de liste:

def divide_list_to_chunks(list_, n):
    return [list_[start::n] for start in range(n)]
liscju
la source
Cela ne résout pas le problème de rendre tous les morceaux même.
SuperBeasedMan
0

Une autre façon serait quelque chose comme ça, l'idée ici est d'utiliser le mérou, mais de s'en débarrasser None. Dans ce cas, nous aurons tous les 'small_parts' formés à partir des éléments de la première partie de la liste, et les 'large_parts' de la dernière partie de la liste. La longueur des «parties plus grandes» est len ​​(small_parts) + 1. Nous devons considérer x comme deux sous-parties différentes.

from itertools import izip_longest

import numpy as np

def grouper(n, iterable, fillvalue=None): # This is grouper from itertools
    "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
    args = [iter(iterable)] * n
    return izip_longest(fillvalue=fillvalue, *args)

def another_chunk(x,num):
    extra_ele = len(x)%num #gives number of parts that will have an extra element 
    small_part = int(np.floor(len(x)/num)) #gives number of elements in a small part

    new_x = list(grouper(small_part,x[:small_part*(num-extra_ele)]))
    new_x.extend(list(grouper(small_part+1,x[small_part*(num-extra_ele):])))

    return new_x

La façon dont je l'ai configuré renvoie une liste de tuples:

>>> x = range(14)
>>> another_chunk(x,3)
[(0, 1, 2, 3), (4, 5, 6, 7, 8), (9, 10, 11, 12, 13)]
>>> another_chunk(x,4)
[(0, 1, 2), (3, 4, 5), (6, 7, 8, 9), (10, 11, 12, 13)]
>>> another_chunk(x,5)
[(0, 1), (2, 3, 4), (5, 6, 7), (8, 9, 10), (11, 12, 13)]
>>> 
Akavall
la source
0

Voici une autre variante qui répartit les éléments "restants" uniformément entre tous les morceaux, un à la fois jusqu'à ce qu'il n'en reste plus. Dans cette implémentation, les plus gros morceaux se produisent au début du processus.

def chunks(l, k):
  """ Yield k successive chunks from l."""
  if k < 1:
    yield []
    raise StopIteration
  n = len(l)
  avg = n/k
  remainders = n % k
  start, end = 0, avg
  while start < n:
    if remainders > 0:
      end = end + 1
      remainders = remainders - 1
    yield l[start:end]
    start, end = end, end+avg

Par exemple, générez 4 blocs à partir d'une liste de 14 éléments:

>>> list(chunks(range(14), 4))
[[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10], [11, 12, 13]]
>>> map(len, list(chunks(range(14), 4)))
[4, 4, 3, 3]
jreyes
la source
0

La même chose que de travail de réponse, mais prend en compte les listes de la taille plus petite que le nombre de chuncks.

def chunkify(lst,n):
    [ lst[i::n] for i in xrange(n if n < len(lst) else len(lst)) ]

si n (nombre de morceaux) est 7 et lst (la liste à diviser) est [1, 2, 3] les morceaux sont [[0], [1], [2]] au lieu de [[0], [1 ], [2], [], [], [], []]

Ilya Touvschev
la source
0

Vous pouvez également utiliser:

split=lambda x,n: x if not x else [x[:n]]+[split([] if not -(len(x)-n) else x[-(len(x)-n):],n)][0]

split([1,2,3,4,5,6,7,8,9],2)

[[1, 2], [3, 4], [5, 6], [7, 8], [9]]
Carlos del Ojo
la source
0
def evenly(l, n):
    len_ = len(l)
    split_size = len_ // n
    split_size = n if not split_size else split_size
    offsets = [i for i in range(0, len_, split_size)]
    return [l[offset:offset + split_size] for offset in offsets]

Exemple:

l = [a for a in range(97)] devrait être composé de 10 parties, chacune ayant 9 éléments sauf le dernier.

Production:

[[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, 75, 76, 77, 78, 79, 80],
 [81, 82, 83, 84, 85, 86, 87, 88, 89],
 [90, 91, 92, 93, 94, 95, 96]]
emremrah
la source
0

Supposons que vous souhaitiez diviser une liste [1, 2, 3, 4, 5, 6, 7, 8] en 3 listes d'éléments

comme [[1,2,3], [4, 5, 6], [7, 8]] , où si les derniers éléments restants sont inférieurs à 3, ils sont regroupés.

my_list = [1, 2, 3, 4, 5, 6, 7, 8]
my_list2 = [my_list[i:i+3] for i in range(0, len(my_list), 3)]
print(my_list2)

Sortie: [[1,2,3], [4, 5, 6], [7, 8]]

Où la longueur d'une partie est 3. Remplacez 3 par votre propre taille de morceau.

Ali Sajjad
la source
0

1>

import numpy as np

data # your array

total_length = len(data)
separate = 10
sub_array_size = total_length // separate
safe_separate = sub_array_size * separate

splited_lists = np.split(np.array(data[:safe_separate]), separate)
splited_lists[separate - 1] = np.concatenate(splited_lists[separate - 1], 
np.array(data[safe_separate:total_length]))

splited_lists # your output

2>

splited_lists = np.array_split(np.array(data), separate)
Bbake Waikhom
la source
0
def chunk_array(array : List, n: int) -> List[List]:
    chunk_size = len(array) // n 
    chunks = []
    i = 0
    while i < len(array):
        # if less than chunk_size left add the remainder to last element
        if len(array) - (i + chunk_size + 1) < 0:
            chunks[-1].append(*array[i:i + chunk_size])
            break
        else:
            chunks.append(array[i:i + chunk_size])
            i += chunk_size
    return chunks

voici ma version (inspirée de Max's)

Solal Baudoin
la source
-1

Arrondir l'espace linspace et l'utiliser comme index est une solution plus simple que ce que propose amit12690.

function chunks=chunkit(array,num)

index = round(linspace(0,size(array,2),num+1));

chunks = cell(1,num);

for x = 1:num
chunks{x} = array(:,index(x)+1:index(x+1));
end
end
Galliwuzz
la source
-1
#!/usr/bin/python


first_names = ['Steve', 'Jane', 'Sara', 'Mary','Jack','Bob', 'Bily', 'Boni', 'Chris','Sori', 'Will', 'Won','Li']

def chunks(l, n):
for i in range(0, len(l), n):
    # Create an index range for l of n items:
    yield l[i:i+n]

result = list(chunks(first_names, 5))
print result

Choisi à partir de ce lien , et c'est ce qui m'a aidé. J'avais une liste prédéfinie.

swateek
la source
-1

disons que vous souhaitez diviser en 5 parties:

p1, p2, p3, p4, p5 = np.split(df, 5)
Danil
la source
4
Cela ne fournit pas de réponse à la question, par exemple comment l'écririez-vous si vous ne savez pas à l'avance que vous voulez la scinder en cinq morceaux. De plus, vous supposez (je suppose) que numpy et peut-être un dataframe pandas. Le PO demande une liste générique.
NickD
-1

J'ai écrit moi-même du code dans ce cas:

def chunk_ports(port_start, port_end, portions):
    if port_end < port_start:
        return None

    total = port_end - port_start + 1

    fractions = int(math.floor(float(total) / portions))

    results = []

    # No enough to chuck.
    if fractions < 1:
        return None

    # Reverse, so any additional items would be in the first range.
    _e = port_end
    for i in range(portions, 0, -1):
        print "i", i

        if i == 1:
            _s = port_start
        else:
            _s = _e - fractions + 1

        results.append((_s, _e))

        _e = _s - 1

    results.reverse()

    return results

divide_ports (1, 10, 9) renverrait

[(1, 2), (3, 3), (4, 4), (5, 5), (6, 6), (7, 7), (8, 8), (9, 9), (10, 10)]
Cipher.Chen
la source
-1

ce code fonctionne pour moi (compatible Python3):

def chunkify(tab, num):
    return [tab[i*num: i*num+num] for i in range(len(tab)//num+(1 if len(tab)%num else 0))]

exemple (pour le type bytearray , mais cela fonctionne également pour les listes ):

b = bytearray(b'\x01\x02\x03\x04\x05\x06\x07\x08')
>>> chunkify(b,3)
[bytearray(b'\x01\x02\x03'), bytearray(b'\x04\x05\x06'), bytearray(b'\x07\x08')]
>>> chunkify(b,4)
[bytearray(b'\x01\x02\x03\x04'), bytearray(b'\x05\x06\x07\x08')]
grafi71
la source
-1

Celui-ci fournit des morceaux de longueur <= n,> = 0

def

 chunkify(lst, n):
    num_chunks = int(math.ceil(len(lst) / float(n))) if n < len(lst) else 1
    return [lst[n*i:n*(i+1)] for i in range(num_chunks)]

par exemple

>>> chunkify(range(11), 3)
[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10]]
>>> chunkify(range(11), 8)
[[0, 1, 2, 3, 4, 5, 6, 7], [8, 9, 10]]
Anthony Manning-Franklin
la source
-1

J'ai essayé la plupart des solutions, mais elles n'ont pas fonctionné pour mon cas, je crée donc une nouvelle fonction qui fonctionne dans la plupart des cas et pour tout type de tableau:

import math

def chunkIt(seq, num):
    seqLen = len(seq)
    total_chunks = math.ceil(seqLen / num)
    items_per_chunk = num
    out = []
    last = 0

    while last < seqLen:
        out.append(seq[last:(last + items_per_chunk)])
        last += items_per_chunk

    return out
Ângelo Polotto
la source