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


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.


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)


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

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

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)).


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)).


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.


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

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


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

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

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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.