Como enumerar um intervalo de números começando em 1


154

Estou usando o Python 2.5, quero uma enumeração como essa (começando em 1 em vez de 0):

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

Eu sei que no Python 2.6 você pode fazer: h = enumerar (range (2000, 2005), 1) para dar o resultado acima, mas no python2.5 você não pode ...

Usando python2.5:

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

Alguém sabe uma maneira de obter o resultado desejado no python 2.5?

Obrigado,

Jeff


4
Apenas curioso, pois sou alguém que não fez muito no caminho do Python profissionalmente. Você está limitado ao Python 2.5 porque sua empresa não deseja fazer a atualização por motivos de compatibilidade?
21710 Sean

2
Todas as versões 2.x são compatíveis com versões anteriores, portanto não há razão.
Jochen Ritzel

Diga isso para alguns módulos - há um fora poucos há que o trabalho em Py 2,5, mas não Py 2.6
xorsyst

Respostas:


179

Como você já mencionou, isso é simples de fazer no Python 2.6 ou mais recente:

enumerate(range(2000, 2005), 1)

O Python 2.5 e mais antigo não suportam o startparâmetro, portanto, você pode criar dois objetos de intervalo e compactá-los:

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

Resultado:

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

Se você deseja criar um gerador em vez de uma lista, use o izip .


usando izipe xrangeestaria mais próximo para enumerar
John La Rooy

7
Esta resposta está desatualizada, agora você pode colocar exatamente enumerate(iterable, start=1)como no Python 2.6.
Fredrick Brennan

@frb: Você leu a pergunta? Ele já conhece a solução para o Python 2.6. Ele pediu especificamente uma solução que funcione no Python 2.5.
22613 Mark Byers

1
@ MarkByers Aparentemente, sou cego :) Sinto muito por isso. (Este é # 1 no Google para "enumerar a partir de 1")
Fredrick Brennan

2
@ 8chan Sim, eu acabei de chegar do Google busca "Não começa enumerate de python zero" :)
Baxx

166

Apenas para colocar isso aqui por motivos de posteridade, no 2.6, o parâmetro "start" foi adicionado para enumerar da seguinte forma:

enumerate(sequence, start=1)


26
Observe que isso não pula o primeiro item da lista, compensa o índice pelo valor inicial, assim você obteria uma matriz fora dos limites se fizesse algo como: sequence[i]no seu código.
Phyatt #

14

Fácil, basta definir sua própria função que faz o que você deseja:

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

12

Python 3

Documentação oficial: enumerate(iterable, start=0)

Então você usaria assim:

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

A maneira mais simples de fazer no Python 2.5 exatamente o que você pergunta:

import itertools as it

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

Se você deseja uma lista, como parece, use zipem vez de it.izip.

(Como regra geral, a melhor maneira de fazer uma lista com um gerador ou qualquer outro X iterável não é [x for x in X], mas sim 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

Agora h = list(enumerate(xrange(2000, 2005), 1))funciona.


6

enumerar é trivial e, portanto, é reimplementá-lo para aceitar um início:

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

Observe que isso não quebra o código usando enumerate sem o argumento start. Como alternativa, esse oneliner pode ser mais elegante e possivelmente mais rápido, mas quebra outros usos do enumerate:

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

O último foi pura bobagem. @Duncan acertou a embalagem.


Sim, total absurdo. Algo nesse sentido realmente funcionaria, por exemplo, em Haskell (currying é a coisa mais natural que existe nessa língua e, devido à sua preguiça, uma função que faz uma lista é muito semelhante a uma expressão geradorag). Mas isso não me desculpa - usuário python de longa data - escrevendo BS. Obrigado por apontar isso.

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

enumerar deve ser um gerador. a criação de uma lista inteira de uma só vez apenas para repetir que muitas vezes não é aceitável
John La Rooy

Generalizado: lista start = 4 (enumerar (intervalo (início) + intervalo (1999, 2005))) [início:]
Tony Veijalainen

intervalo é no entanto lista em 2.52
Tony Veijalainen

3

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


1
Ele não pode fazer isso no Python 2.5. O parâmetro start foi introduzido no Python 2.6: docs.python.org/library/functions.html#enumerate . Ele também menciona isso na questão.
Mark Byers

Respondi isso antes da edição inicial, quando o código não foi formatado e o problema me pareceu ser o uso de um gerador em vez de uma lista.
Chris B.

++: Essa é a maneira de fazê-lo
Nas Banov

2

Ok, eu me sinto um pouco estúpido aqui ... qual é o motivo para não fazer isso com algo parecido
[(a+1,b) for (a,b) in enumerate(r)]? Se você não funcionar, não há problema:

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

Como isso é um pouco detalhado, eu recomendo escrever sua própria função para generalizá-la:

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

2
enumerar deve ser um gerador. a criação de uma lista inteira de uma só vez apenas para repetir que muitas vezes não é aceitável
John La Rooy

0

Não sei como essas postagens poderiam ser mais complicadas do que as seguintes:

# Just pass the start argument to enumerate ...
for i,word in enumerate(allWords, 1):
    word2idx[word]=i
    idx2word[i]=word
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.