web-dev-qa-db-fra.com

Manière pythonique de retourner la liste de chaque nième élément dans une liste plus grande

Supposons que nous ayons une liste de nombres allant de 0 à 1000. Existe-t-il un moyen efficace/pythonique de produire une liste du premier et de tous les dix éléments suivants, c.-à-d. [0, 10, 20, 30, ... ]?

Oui, je peux le faire en utilisant une boucle for, mais je me demande s’il existe un moyen plus ordonné de le faire, peut-être même sur une seule ligne?

144
p.brown
>>> l = range(165)
>>> l[0::10]
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160]

EDIT: juste pour le plaisir, une petite comparaison de timing (en ignorant la condition limite):

$ python -m timeit -s "l = range(1000)" "l1 = [x for x in l if x % 10 == 0]"
1000 loops, best of 3: 525 usec per loop
$ python -m timeit -s "l = range(1000)" "l1 = l[0::10]"
100000 loops, best of 3: 4.02 usec per loop
243
Ned Deily
  1. source_list[::10] Est le plus évident, mais cela ne fonctionne pas pour toutes les itérations et la mémoire n'est pas efficace pour les grandes listes.
  2. itertools.islice(source_sequence, 0, None, 10) fonctionne pour tous les itératifs et est efficace dans la mémoire, mais n'est probablement pas la solution la plus rapide pour les grandes listes et les grandes étapes.
  3. (source_list[i] for i in xrange(0, len(source_list), 10))
47
Denis Otkidach

Vous pouvez utiliser l'opérateur slice comme ceci:

l = [1,2,3,4,5]
l2 = l[::2] # get subsequent 2nd item
23
Nick Dandoulakis

De manuel: s[i:j:k] slice of s from i to j with step k

li = range(100)
sub = li[0::10]

>>> sub
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
15
tuergeist
newlist = oldlist[::10]

Ceci sélectionne chaque 10ème élément de la liste.

12
David Z

Pourquoi ne pas simplement utiliser une étape paramètre de plage fonction aussi pour obtenir:

l = range(0, 1000, 10)

A titre de comparaison, sur ma machine:

H:\>python -m timeit -s "l = range(1000)" "l1 = [x for x in l if x % 10 == 0]"
10000 loops, best of 3: 90.8 usec per loop
H:\>python -m timeit -s "l = range(1000)" "l1 = l[0::10]"
1000000 loops, best of 3: 0.861 usec per loop
H:\>python -m timeit -s "l = range(0, 1000, 10)"
100000000 loops, best of 3: 0.0172 usec per loop
3
van
existing_list = range(0, 1001)
filtered_list = [i for i in existing_list if i % 10 == 0]
3
lutz

Voici une meilleure implémentation d'une compréhension de la liste "chaque 10ème élément", qui n'utilise pas le contenu de la liste dans le cadre du test d'adhésion:

>>> l = range(165)
>>> [ item for i,item in enumerate(l) if i%10==0 ]
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160]
>>> l = list("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
>>> [ item for i,item in enumerate(l) if i%10==0 ]
['A', 'K', 'U']

Mais cela reste encore beaucoup plus lent que le simple découpage de la liste.

2
PaulMcG