243 votes

Diviser une liste python en d'autres "sous-listes", c'est-à-dire des listes plus petites.

J'ai une liste en python qui se compte en milliers. Quelque chose comme :

data=["I","am","a","python","programmer".....]

où, len(data)= say 1003

Je voudrais maintenant créer un sous-ensemble de cette liste (données) en divisant la liste originale en morceaux de 100. Donc, à la fin, j'aimerais avoir quelque chose comme.. :

data_chunk1=[.....] #first 100 items of list data
data_chunk2=[.....] #second 100 items of list data
.
.
.
data_chunk11=[.....] # remainder of the entries,& its len <=100, len(data_chunk_11)=3

Existe-t-il un moyen pythique de réaliser cette tâche ? Je peux évidemment utiliser data[0:100] et ainsi de suite, mais je suppose que c'est terriblement non pythonique et très inefficace.

Merci beaucoup.

11 votes

Vous pourriez utiliser la fonction array_split de numpy Par exemple, np.array_split(np.array(data), 20) pour les diviser en 20 morceaux de taille presque égale. Pour être sûr que les morceaux sont exactement de la même taille, utilisez np.split .

435voto

DanRedux Points 3018

Je dirais

chunks = [data[x:x+100] for x in range(0, len(data), 100)]

Si vous utilisez python 2.x au lieu de 3.x, vous pouvez être plus économe en mémoire en utilisant xrange() en changeant le code ci-dessus en :

chunks = [data[x:x+100] for x in xrange(0, len(data), 100)]

8 votes

C'est aussi ce que je ferais. Vous pouvez peut-être le faire d'une manière plus "pythique" avec itertools, mais ce sera laid comme le péché !

14 votes

Si vous avez une liste et que vous voulez une liste, il n'y a aucune raison de s'embêter avec itertools. Ils n'ont de sens que si vous voulez diviser un flux de données sans jamais créer l'ensemble.

6 votes

Utiliser itertools serait en fait la manière la moins pythonique de le faire, n'est-ce pas ?

41voto

Sven Marnach Points 133943

En fait, je pense que l'utilisation de tranches simples est la meilleure solution dans ce cas :

for i in range(0, len(data), 100):
    chunk = data[i:i + 100]
    ...

Si vous voulez éviter de copier les tranches, vous pouvez utiliser itertools.islice() mais cela ne semble pas nécessaire ici.

Le site itertools() La documentation contient également le fameux motif "mérou" :

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

Il faudrait le modifier pour traiter correctement le dernier morceau. Je pense donc que la solution directe consistant à utiliser des tranches simples est préférable.

1 votes

Merci pour la réponse. J'ai pensé à votre première solution en tranches simples, mais je me suis dit que c'était peut-être trop inefficace et trop naïf de ma part Je suis un peu surpris qu'il n'y ait pas une méthode pythonique (one liners) pour réaliser cette tâche :(

18voto

inspectorG4dget Points 25092
chunks = [data[100*i:100*(i+1)] for i in range(len(data)/100 + 1)]

Ceci est équivalent à la réponse acceptée. Par exemple, raccourcir à des lots de 10 pour plus de lisibilité :

data = range(35)
print [data[x:x+10] for x in xrange(0, len(data), 10)]
print [data[10*i:10*(i+1)] for i in range(len(data)/10 + 1)]

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

3 votes

Ce n'est pas ce qui est demandé.

1 votes

En fait, il est équivalent, à l'exception d'un bug où le dernier lot est manquant, maintenant corrigé.

1 votes

Mais que faire si vos données ne sont pas divisibles par 10 ?

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