Aufzählen eines Zahlenbereichs ab 1

154

Ich verwende Python 2.5, ich möchte eine Aufzählung wie diese (beginnend bei 1 statt 0):

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

Ich weiß, dass Sie in Python 2.6 Folgendes tun können: h = Aufzählung (Bereich (2000, 2005), 1), um das obige Ergebnis zu erhalten, aber in Python2.5 können Sie nicht ...

Verwenden von Python2.5:

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

Kennt jemand einen Weg, um das gewünschte Ergebnis in Python 2.5 zu erzielen?

Vielen Dank,

Jeff

JeffTaggary
quelle
4
Nur neugierig, denn ich bin jemand, der beruflich nicht viel mit Python zu tun hat. Sind Sie auf Python 2.5 beschränkt, weil Ihr Unternehmen das Upgrade aus Kompatibilitätsgründen nicht durchführen möchte?
Sean
2
Alle 2.x-Versionen sind abwärtskompatibel, das ist also kein Grund.
Jochen Ritzel
Sagen Sie das einigen Modulen - es gibt einige, die in Py 2.5 funktionieren, aber nicht in Py 2.6
xorsyst

Antworten:

179

Wie Sie bereits erwähnt haben, ist dies in Python 2.6 oder höher unkompliziert:

enumerate(range(2000, 2005), 1)

Python 2.5 und älter unterstützen den startParameter nicht. Stattdessen können Sie zwei Bereichsobjekte erstellen und diese komprimieren:

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

Ergebnis:

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

Wenn Sie einen Generator anstelle einer Liste erstellen möchten, können Sie stattdessen izip verwenden.

Mark Byers
quelle
mit izipund xrangewäre näher zu zählen
John La Rooy
7
Diese Antwort ist veraltet. Sie können sie jetzt enumerate(iterable, start=1)ab Python 2.6 verwenden.
Fredrick Brennan
@frb: Hast du die Frage gelesen? Er kennt bereits die Lösung für Python 2.6. Er bat ausdrücklich um eine Lösung, die in Python 2.5 funktioniert.
Mark Byers
1
@ MarkByers Anscheinend bin ich blind :) Tut mir wirklich leid. (Dies ist die Nummer 1 in Google für "Aufzählung ab 1")
Fredrick Brennan
2
@ 8chan yep, ich bin gerade von der Google-Suche hierher gekommen "Aufzählung startet von Null Python" :)
Baxx
166

Um dies der Nachwelt zuliebe hier zu formulieren, wurde in 2.6 der Parameter "start" hinzugefügt, um wie folgt aufzuzählen:

enumerate(sequence, start=1)

Dhackner
quelle
26
Beachten Sie, dass dadurch nicht das erste Element in der Liste übersprungen wird, sondern der Index um den Startwert versetzt wird, sodass Sie ein Array außerhalb der Grenzen erhalten würden, wenn Sie Folgendes tun würden: sequence[i]in Ihrem Code.
Phyatt
14

Einfach, definieren Sie einfach Ihre eigene Funktion, die das tut, was Sie wollen:

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

Python 3

Offizielle Dokumentation: enumerate(iterable, start=0)

Sie würden es also so verwenden:

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

Der einfachste Weg, in Python 2.5 genau das zu tun, worüber Sie fragen:

import itertools as it

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

Wenn Sie eine Liste wünschen, wie Sie scheinen, verwenden Sie zipanstelle von it.izip.

(Übrigens ist der beste Weg, eine Liste aus einem Generator oder einem anderen iterierbaren X zu erstellen, in der Regel nicht [x for x in X] , sondern list(X)).

Alex Martelli
quelle
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

Funktioniert jetzt h = list(enumerate(xrange(2000, 2005), 1)).

Jochen Ritzel
quelle
6

Aufzählung ist trivial, ebenso wie die Neuimplementierung, um einen Start zu akzeptieren:

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

Beachten Sie, dass dies den Code nicht durch Aufzählung ohne Startargument unterbricht. Alternativ kann dieser Oneliner eleganter und möglicherweise schneller sein, bricht jedoch andere Verwendungszwecke der Aufzählung:

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

Letzteres war purer Unsinn. @ Duncan hat den Wrapper richtig gemacht.


quelle
Ja, totaler Unsinn. Etwas in dieser Richtung würde tatsächlich in z. B. Haskell funktionieren (Currying ist die natürlichste Sache in dieser Sprache, und aufgrund seiner Faulheit ist eine Funktion, die eine Liste erstellt, einem Generatorausdruck sehr ähnlich). Aber das entschuldigt mich nicht - langjähriger Python-Benutzer - BS zu schreiben. Vielen Dank für den Hinweis.
5
>>> list(enumerate(range(1999, 2005)))[1:]
[(1, 2000), (2, 2001), (3, 2002), (4, 2003), (5, 2004)]
JAB
quelle
Aufzählung sollte ein Generator sein. Erstellen einer ganzen Liste auf einmal, nur um zu wiederholen, wenn oft nicht akzeptabel
John La Rooy
Verallgemeinert: Start = 4 Liste (Aufzählung (Bereich (Start) + Bereich (1999, 2005))) [Start:]
Tony Veijalainen
Bereich ist jedoch Liste in 2.52
Tony Veijalainen
3

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

Chris B.
quelle
1
Er kann dies in Python 2.5 nicht tun. Der Startparameter wurde in Python 2.6 eingeführt: docs.python.org/library/functions.html#enumerate . Er erwähnt dies auch in der Frage.
Mark Byers
Beantwortete dies vor der ersten Bearbeitung, als der Code unformatiert war und das Problem für mich die Verwendung eines Generators anstelle einer Liste zu sein schien.
Chris B.
++: das ist der Weg, um es zu tun
Nas Banov
2

Ok, ich fühle mich hier ein bisschen dumm ... was ist der Grund, es nicht einfach mit so etwas zu machen
[(a+1,b) for (a,b) in enumerate(r)]? Wenn Sie nicht funktionieren, auch kein Problem:

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

Da dies etwas ausführlich ist, würde ich empfehlen, eine eigene Funktion zu schreiben, um sie zu verallgemeinern:

def enumerate_at(xs, start):
    return ((tup[0]+start, tup[1]) for tup in enumerate(xs))
Eli Courtwright
quelle
2
Aufzählung sollte ein Generator sein. Erstellen einer ganzen Liste auf einmal, nur um zu wiederholen, wenn oft nicht akzeptabel
John La Rooy
0

Ich weiß nicht, wie diese Beiträge möglicherweise komplizierter gemacht werden könnten als die folgenden:

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