Jak wyliczyć zakres liczb zaczynający się od 1

154

Używam Pythona 2.5, chcę wyliczenia w ten sposób (zaczynając od 1 zamiast 0):

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

Wiem, że w Pythonie 2.6 możesz zrobić: h = enumerate (range (2000, 2005), 1), aby uzyskać powyższy wynik, ale w pythonie 2.5 nie możesz ...

Korzystanie z python2.5:

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

Czy ktoś zna sposób na uzyskanie pożądanego wyniku w Pythonie 2.5?

Dzięki,

Jeff

JeffTaggary
źródło
4
Jestem po prostu ciekawy, ponieważ jestem kimś, kto nie zrobił wiele profesjonalnie w zakresie Pythona. Czy jesteś ograniczony do Pythona 2.5, ponieważ Twoja firma nie chce dokonywać aktualizacji ze względu na kompatybilność?
Sean,
2
Wszystkie wersje 2.x są wstecznie kompatybilne, więc nie ma powodu.
Jochen Ritzel
Powiedz to niektórym modułom - jest kilka, które działają w Py 2.5, ale nie w Py 2.6
xorsyst

Odpowiedzi:

179

Jak już wspomniałeś, jest to łatwe do zrobienia w Pythonie 2.6 lub nowszym:

enumerate(range(2000, 2005), 1)

Python 2.5 i starsze nie obsługują tego startparametru, więc zamiast tego możesz utworzyć dwa obiekty zakresu i spakować je:

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

Wynik:

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

Jeśli chcesz utworzyć generator zamiast listy, możesz zamiast tego użyć izip .

Mark Byers
źródło
używając izipi xrangebyłby bliżej wyliczenia
John La Rooy
7
Ta odpowiedź jest nieaktualna, możesz teraz umieścić ją tak samo, enumerate(iterable, start=1)jak w Pythonie 2.6.
Fredrick Brennan
@frb: Czy przeczytałeś pytanie? Zna już rozwiązanie dla Pythona 2.6. Specjalnie poprosił o rozwiązanie działające w Pythonie 2.5.
Mark Byers,
1
@MarkByers Najwyraźniej jestem ślepy :) Naprawdę mi przykro. (To jest nr 1 w Google pod względem „wyliczenia zaczynającego się od 1”)
Fredrick Brennan,
2
@ 8chan tak, właśnie dotarłem tutaj z wyszukiwarki Google „czy wylicza początek od zera pythona” :)
baxx
166

Żeby umieścić to tutaj ze względu na potomność, w 2.6 dodano parametr "start" w celu wyliczenia w następujący sposób:

enumerate(sequence, start=1)

dhackner
źródło
26
Zauważ, że to nie pomija pierwszego elementu na liście, przesuwa indeks o wartość początkową, więc możesz uzyskać tablicę poza granicami, jeśli zrobiłeś coś takiego: sequence[i]w swoim kodzie.
phyatt
14

Łatwo, po prostu zdefiniuj własną funkcję, która robi to, co chcesz:

def enum(seq, start=0):
    for i, x in enumerate(seq):
        yield i+start, x
Duncan
źródło
12

Python 3

Oficjalna dokumentacja: enumerate(iterable, start=0)

Więc użyłbyś tego w ten sposób:

>>> 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
źródło
10

Najprościej zrobić w Pythonie 2.5 dokładnie to, o co pytasz:

import itertools as it

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

Jeśli chcesz otrzymać listę, jak się wydaje, użyj zipzamiast it.izip.

(BTW, z reguły najlepszym sposobem na utworzenie listy z generatora lub innego iterowalnego X nie jest [x for x in X], ale raczej list(X)).

Alex Martelli
źródło
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

Teraz h = list(enumerate(xrange(2000, 2005), 1))działa.

Jochen Ritzel
źródło
6

enumerate jest trywialne, a więc jest ponownie implementowane, aby zaakceptować start:

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

Należy zauważyć, że nie powoduje to złamania kodu przy użyciu wyliczenia bez argumentu start. Alternatywnie, ten oneliner może być bardziej elegancki i prawdopodobnie szybszy, ale łamie inne zastosowania wyliczenia:

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

To ostatnie było czystym nonsensem. @Duncan ma rację.


źródło
Tak, totalny nonsens. Coś podobnego by działało np. W Haskellu (currying jest najbardziej naturalną rzeczą w tym języku, a funkcja pobierająca listę jest bardzo podobna do wyrażenia generatora g). Ale to nie usprawiedliwia mnie - wieloletniego użytkownika Pythona - piszącego BS. Dzięki za wskazanie tego.
5
>>> list(enumerate(range(1999, 2005)))[1:]
[(1, 2000), (2, 2001), (3, 2002), (4, 2003), (5, 2004)]
UKŁUCIE
źródło
enumerate powinien być generatorem. tworząc całą listę na raz tylko iteracyjne nad jeśli często nie do zaakceptowania
John La Rooy
Uogólnione: początek = 4 lista (wyliczenie (zakres (początek) + zakres (1999, 2005))) [początek:]
Tony Veijalainen
zakres jest jednak lista w 2.52
Tony Veijalainen
3

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

Chris B.
źródło
1
Nie może tego zrobić w Pythonie 2.5. Parametr start został wprowadzony w Pythonie 2.6: docs.python.org/library/functions.html#enumerate . Wspomina o tym również w pytaniu.
Mark Byers,
Odpowiedziałem na to przed początkową edycją, kiedy kod był niesformatowany i wydawało mi się, że problem polega na użyciu generatora zamiast listy.
Chris B.
++: tak to się robi
Nas Banov
2

Ok, czuję się tu trochę głupio ... jaki jest powód, żeby tego nie robić po prostu z czymś takim
[(a+1,b) for (a,b) in enumerate(r)]? Jeśli nie będziesz działać, nie ma też problemu:

>>> 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
źródło
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)]

Ponieważ jest to dość rozwlekłe, polecam napisanie własnej funkcji, aby ją uogólnić:

def enumerate_at(xs, start):
    return ((tup[0]+start, tup[1]) for tup in enumerate(xs))
Eli Courtwright
źródło
2
enumerate powinien być generatorem. tworząc całą listę na raz tylko iteracyjne nad jeśli często nie do zaakceptowania
John La Rooy
0

Nie wiem, jak te posty mogłyby być bardziej skomplikowane niż następujące:

# Just pass the start argument to enumerate ...
for i,word in enumerate(allWords, 1):
    word2idx[word]=i
    idx2word[i]=word
bmc
źródło