Come enumerare un intervallo di numeri a partire da 1


154

Sto usando Python 2.5, voglio un'enumerazione simile (a partire da 1 anziché 0):

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

So che in Python 2.6 puoi fare: h = enumerate (range (2000, 2005), 1) per dare il risultato sopra ma in python2.5 non puoi ...

Utilizzando python2.5:

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

Qualcuno conosce un modo per ottenere il risultato desiderato in Python 2.5?

Grazie,

Jeff


4
Solo curioso, dato che sono qualcuno che non ha fatto molto in termini di Python in modo professionale. Sei limitato a Python 2.5 perché la tua azienda non vuole effettuare l'aggiornamento per motivi di compatibilità?
Sean,

2
Tutte le versioni 2.x sono retrocompatibili, quindi non c'è motivo.
Jochen Ritzel,

Dillo ad alcuni moduli - ce ne sono alcuni là fuori che funzionano in Py 2.5 ma non in Py 2.6
xorsyst

Risposte:


179

Come hai già detto, questo è semplice da fare in Python 2.6 o versioni successive:

enumerate(range(2000, 2005), 1)

Python 2.5 e versioni precedenti non supportano il startparametro, quindi è possibile creare due oggetti intervallo e comprimerli:

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

Risultato:

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

Se si desidera creare un generatore anziché un elenco, è possibile utilizzare invece izip .


usando izipe xrangesarebbe più vicino all'enumerazione
John La Rooy,

7
Questa risposta è obsoleta, ora puoi inserirla proprio enumerate(iterable, start=1)come in Python 2.6.
Fredrick Brennan,

@frb: hai letto la domanda? Conosce già la soluzione per Python 2.6. Ha specificamente richiesto una soluzione che funzioni in Python 2.5.
Mark Byers,

1
@MarkByers Apparentemente sono cieco :) Mi dispiace davvero per quello. (Questo è il numero 1 in Google per "enumerare a partire da 1")
Fredrick Brennan,

2
@ 8chan sì, sono appena arrivato dalla ricerca di Google "enumera inizia da zero pitone" :)
baxx

166

Solo per metterlo qui per amor dei posteri, in 2.6 è stato aggiunto il parametro "start" per enumerare in questo modo:

enumerate(sequence, start=1)


26
Nota che questo non salta il primo elemento nell'elenco, compensa l'indice dal valore iniziale, quindi otterrai una matrice fuori dai limiti se facessi qualcosa del genere: sequence[i]nel tuo codice.
Phyatt,

14

Facile, basta definire la tua funzione che fa quello che vuoi:

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

12

Python 3

Documentazione ufficiale: enumerate(iterable, start=0)

Quindi lo useresti in questo modo:

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

Il modo più semplice di fare in Python 2.5 esattamente quello che chiedi:

import itertools as it

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

Se vuoi un elenco, come sembri, usa zipal posto di it.izip.

(A proposito, come regola generale, il modo migliore per creare un elenco da un generatore o da qualsiasi altra X iterabile non è [x for x in X], ma piuttosto 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

Adesso h = list(enumerate(xrange(2000, 2005), 1))funziona.


6

enumerare è banale, quindi lo sta implementando nuovamente per accettare un inizio:

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

Nota che questo non rompe il codice usando enumerate senza argomento start. In alternativa, questo oneliner può essere più elegante e forse più veloce, ma rompe altri usi di enumerare:

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

Quest'ultima era pura assurdità. @Duncan ha capito bene l'involucro.


Sì, totale assurdità. Qualcosa del genere funzionerebbe, ad esempio, in Haskell (il curry è la cosa più naturale in assoluto in quella lingua e, a causa della sua pigrizia, una funzione che prende una lista è molto simile all'espressione di un generatore). Ma questo non mi scusa - utente di Python di vecchia data - scrivere BS. Grazie per segnalarlo.

5
>>> list(enumerate(range(1999, 2005)))[1:]
[(1, 2000), (2, 2001), (3, 2002), (4, 2003), (5, 2004)]

enumerare dovrebbe essere un generatore. creando un intero elenco in una sola volta solo per scorrere se spesso non accettabile
John La Rooy,

Generalized: start = 4 list (enumerate (range (start) + range (1999, 2005))) [inizio:]
Tony Veijalainen

l'intervallo è tuttavia elencato in 2.52
Tony Veijalainen,

3

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


1
Non può farlo in Python 2.5. Il parametro start è stato introdotto in Python 2.6: docs.python.org/library/functions.html#enumerate . Lo menziona anche nella domanda.
Mark Byers,

Ho risposto a questo prima della modifica iniziale, quando il codice non era formattato e il problema mi sembrava essere l'uso di un generatore anziché di un elenco.
Chris B.

++: questo è il modo di farlo
Nas Banov,

2

Ok, mi sento un po 'stupido qui ... qual è il motivo per non farlo con qualcosa del genere
[(a+1,b) for (a,b) in enumerate(r)]? Se non funzionerai, nessun problema neanche:

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

Poiché questo è in qualche modo dettagliato, ti consiglio di scrivere la tua funzione per generalizzarla:

def enumerate_at(xs, start):
    return ((tup[0]+start, tup[1]) for tup in enumerate(xs))

2
enumerare dovrebbe essere un generatore. creando un intero elenco in una sola volta solo per scorrere se spesso non accettabile
John La Rooy,

0

Non so come questi post potrebbero essere resi più complicati di quanto segue:

# Just pass the start argument to enumerate ...
for i,word in enumerate(allWords, 1):
    word2idx[word]=i
    idx2word[i]=word
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.