212 votes

le fractionnement d'une liste de taille arbitraire dans environ seulement en N parties égales

quelle est la meilleure façon de diviser une liste dans à peu près égale des parties? par exemple, si j'ai une liste avec 54 éléments et je tiens à le diviser en 3 parties à peu près égales? J'aimerais les pièces à être aussi régulière que possible, espérons-le, l'attribution des éléments qui n'entrent pas dans une manière qui donne le plus de parties égales. pour donner un cas concret, si la liste contient 7 éléments et je tiens à le diviser en 2 parties, j'avais idéalement voulez obtenir les 3 premiers éléments dans un bac, la deuxième devrait avoir 4 éléments.

donc, pour résumer, je suis à la recherche de quelque chose comme even_split(l, n) qui casse l dans à peu près n-les différentes parties.

le mieux je pense est quelque chose qui a été posté ici:

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

exemple:

l = range(54)
chunks_of_three = chunks(l, 3)

mais cela donne des morceaux de 3, plutôt que 3 parties égales. Je pourrais simplement parcourir et de prendre le premier élément de chaque colonne, appel que la première partie, puis prendre la deuxième et de la mettre dans la partie deux, etc. mais cela semble inefficace et peu élégante. il est également contraire à l'ordre de la liste.

toutes les idées sur ce point?

merci.

285voto

tixxit Points 461

Vous pouvez l'écrire assez simplement comme un générateur de liste:

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

Exemple:

>>> list(split(range(11), 3))
[[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10]]

130voto

job Points 3238

Tant que vous ne voulez pas quelque chose de stupide comme continue morceaux:

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

80voto

Max Shawabkeh Points 19030

En voici une 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

Test:

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

20voto

paxdiablo Points 341644

Modifiant le code de rendement n morceaux plutôt que de 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()

ce 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 va affecter les éléments supplémentaires pour le dernier groupe, qui n'est pas parfait, mais bien à l'intérieur de votre cahier des charges de "l'à peu près N parties égales" :-) Par cela, je veux dire 56 éléments serait mieux comme (19,19,18) considérant que cela donne (18,18,20).

Vous pouvez obtenir plus équilibrée de la sortie 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()

sorties:

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

3voto

Utilise grouper():

def chunks(seq, num):
  return grouper(int(math.ceil(len(seq) / float(num))), seq)

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