Comment énumérer une plage de nombres commençant à 1

154

J'utilise Python 2.5, je veux une énumération comme celle-ci (commençant à 1 au lieu de 0):

[(1, 2000), (2, 2001), (3, 2002), (4, 2003), (5, 2004)]

Je sais qu'en Python 2.6 vous pouvez faire: h = enumerate (range (2000, 2005), 1) pour donner le résultat ci-dessus mais en python2.5 vous ne pouvez pas ...

En utilisant python2.5:

>>> h = enumerate(range(2000, 2005))
>>> [x for x in h]
[(0, 2000), (1, 2001), (2, 2002), (3, 2003), (4, 2004)]

Quelqu'un connaît-il un moyen d'obtenir le résultat souhaité dans Python 2.5?

Merci,

Jeff

JeffTaggary
la source
4
Juste curieux, car je suis quelqu'un qui n'a pas fait grand-chose de Python professionnellement. Êtes-vous limité à Python 2.5 parce que votre entreprise ne souhaite pas effectuer la mise à niveau pour des raisons de compatibilité?
Sean
2
Toutes les versions 2.x sont rétrocompatibles, ce n'est donc pas une raison.
Jochen Ritzel
Dites cela à certains modules - il y en a quelques-uns qui fonctionnent dans Py 2.5 mais pas dans Py 2.6
xorsyst

Réponses:

179

Comme vous l'avez déjà mentionné, c'est simple à faire dans Python 2.6 ou plus récent:

enumerate(range(2000, 2005), 1)

Python 2.5 et les versions antérieures ne prennent pas en charge le startparamètre, vous pouvez donc créer deux objets de plage et les compresser:

r = xrange(2000, 2005)
r2 = xrange(1, len(r) + 1)
h = zip(r2, r)
print h

Résultat:

[(1, 2000), (2, 2001), (3, 2002), (4, 2003), (5, 2004)]

Si vous souhaitez créer un générateur au lieu d'une liste, vous pouvez utiliser izip à la place.

Mark Byers
la source
en utilisant izipet xrangeserait plus proche d'énumérer
John La Rooy
7
Cette réponse est bien dépassée, vous pouvez maintenant la mettre à enumerate(iterable, start=1)partir de Python 2.6.
Fredrick Brennan
@frb: Avez-vous lu la question? Il connaît déjà la solution pour Python 2.6. Il a spécifiquement demandé une solution qui fonctionne en Python 2.5.
Mark Byers
1
@MarkByers Apparemment, je suis aveugle :) Vraiment désolé pour ça. (Ceci est n ° 1 dans Google pour "énumérer à partir de 1")
Fredrick Brennan
2
@ 8chan ouais, je viens juste d'arriver à partir de la recherche Google "fait énumérer commence à partir de zéro python" :)
baxx
166

Juste pour mettre ceci ici pour la postérité, dans 2.6 le paramètre "start" a été ajouté pour énumérer comme ceci:

enumerate(sequence, start=1)

dhackner
la source
26
Notez que cela n'ignore pas le premier élément de la liste, cela décale l'index par la valeur de départ, donc vous obtiendrez un tableau hors limites si vous faisiez quelque chose comme: sequence[i]dans votre code.
phyatt
14

Facile, définissez simplement votre propre fonction qui fait ce que vous voulez:

def enum(seq, start=0):
    for i, x in enumerate(seq):
        yield i+start, x
Duncan
la source
12

Python 3

Documentation officielle: enumerate(iterable, start=0)

Donc, vous l'utiliseriez comme ceci:

>>> seasons = ['Spring', 'Summer', 'Fall', 'Winter']

>>> list(enumerate(seasons))
[(0, 'Spring'), (1, 'Summer'), (2, 'Fall'), (3, 'Winter')]

>>> list(enumerate(seasons, start=1))
[(1, 'Spring'), (2, 'Summer'), (3, 'Fall'), (4, 'Winter')]
winklerrr
la source
10

Le moyen le plus simple de faire en Python 2.5 exactement ce que vous demandez:

import itertools as it

... it.izip(it.count(1), xrange(2000, 2005)) ...

Si vous voulez une liste, comme vous semblez, utilisez zipà la place de it.izip.

(BTW, en règle générale, la meilleure façon de faire une liste à partir d'un générateur ou de tout autre X itérable n'est pas [x for x in X] , mais plutôt list(X)).

Alex Martelli
la source
6
from itertools import count, izip

def enumerate(L, n=0):
    return izip( count(n), L)

# if 2.5 has no count
def count(n=0):
    while True:
        yield n
        n+=1

Fonctionne maintenant h = list(enumerate(xrange(2000, 2005), 1)).

Jochen Ritzel
la source
6

enumerate est trivial, tout comme la réimplémentation pour accepter un début:

def enumerate(iterable, start = 0):
    n = start
    for i in iterable:
        yield n, i
        n += 1

Notez que cela n'interrompt pas le code en utilisant enumerate sans argument de démarrage. Alternativement, cet oneliner peut être plus élégant et peut-être plus rapide, mais rompt d'autres utilisations d'énumérer:

enumerate = ((index+1, item) for index, item)

Ce dernier était un pur non-sens. @Duncan a obtenu le bon wrapper.


la source
Oui, un non-sens total. Quelque chose de ce genre fonctionnerait par exemple dans Haskell (le curry est la chose la plus naturelle qui soit dans cette langue, et en raison de sa paresse, une fonction prenant une liste est très similaire à une expressiong de générateur). Mais cela ne m'excuse pas - utilisateur de python de longue date - d'écrire BS. Merci de l'avoir signalé.
5
>>> list(enumerate(range(1999, 2005)))[1:]
[(1, 2000), (2, 2001), (3, 2002), (4, 2003), (5, 2004)]
COUP
la source
enumerate doit être un générateur. créer une liste complète à la fois juste pour itérer si souvent pas acceptable
John La Rooy
Généralisée: start = 4 list (enumerate (range (start) + range (1999, 2005))) [start:]
Tony Veijalainen
la gamme est cependant
listée
3

h = [(i + 1, x) for i, x in enumerate(xrange(2000, 2005))]

Chris B.
la source
1
Il ne peut pas faire cela dans Python 2.5. Le paramètre start a été introduit dans Python 2.6: docs.python.org/library/functions.html#enumerate . Il le mentionne également dans la question.
Mark Byers
J'ai répondu à cela avant l'édition initiale, lorsque le code n'était pas formaté et que le problème me semblait être l'utilisation d'un générateur au lieu d'une liste.
Chris B.
++: c'est la façon de le faire
Nas Banov
2

Ok, je me sens un peu stupide ici ... quelle est la raison de ne pas le faire avec quelque chose comme ça
[(a+1,b) for (a,b) in enumerate(r)]? Si vous ne fonctionnerez pas, pas de problème non plus:

>>> r = range(2000, 2005)
>>> [(a+1,b) for (a,b) in enumerate(r)]
[(1, 2000), (2, 2001), (3, 2002), (4, 2003), (5, 2004)]

>>> enumerate1 = lambda r:((a+1,b) for (a,b) in enumerate(r)) 

>>> list(enumerate1(range(2000,2005)))   # note - generator just like original enumerate()
[(1, 2000), (2, 2001), (3, 2002), (4, 2003), (5, 2004)]
Nas Banov
la source
1
>>> h = enumerate(range(2000, 2005))
>>> [(tup[0]+1, tup[1]) for tup in h]
[(1, 2000), (2, 2001), (3, 2002), (4, 2003), (5, 2004)]

Comme c'est un peu verbeux, je vous recommande d'écrire votre propre fonction pour la généraliser:

def enumerate_at(xs, start):
    return ((tup[0]+start, tup[1]) for tup in enumerate(xs))
Eli Courtwright
la source
2
enumerate doit être un générateur. créer une liste complète à la fois juste pour itérer si souvent pas acceptable
John La Rooy
0

Je ne sais pas comment ces publications pourraient être rendues plus compliquées que les suivantes:

# Just pass the start argument to enumerate ...
for i,word in enumerate(allWords, 1):
    word2idx[word]=i
    idx2word[i]=word
bmc
la source