Cách liệt kê một dãy số bắt đầu từ 1


154

Tôi đang sử dụng Python 2.5, tôi muốn liệt kê như vậy (bắt đầu từ 1 thay vì 0):

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

Tôi biết trong Python 2.6 bạn có thể làm: h = enum Cả (phạm vi (2000, 2005), 1) để đưa ra kết quả trên nhưng trong python2.5 bạn không thể ...

Sử dụng python2,5:

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

Có ai biết một cách để có được kết quả mong muốn trong python 2.5 không?

Cảm ơn,

Jeff


4
Chỉ tò mò thôi, vì tôi là người chưa thực hiện được nhiều cách chuyên nghiệp về Python. Bạn có bị giới hạn ở Python 2.5 không vì công ty của bạn không muốn nâng cấp vì lý do tương thích?
Sean

2
Tất cả các phiên bản 2.x đều tương thích ngược, vì vậy đó không phải là lý do.
Jochen Ritzel

Nói với một số mô-đun - có một số ít hoạt động trong Py 2.5 nhưng không phải Py 2.6
xorsyst

Câu trả lời:


179

Như bạn đã đề cập, điều này rất đơn giản để thực hiện trong Python 2.6 hoặc mới hơn:

enumerate(range(2000, 2005), 1)

Python 2.5 trở lên không hỗ trợ starttham số nên thay vào đó bạn có thể tạo hai đối tượng phạm vi và nén chúng:

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

Kết quả:

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

Nếu bạn muốn tạo một trình tạo thay vì một danh sách thì bạn có thể sử dụng izip để thay thế.


sử dụng izipxrangesẽ gần gũi hơn với liệt kê
John La Rooy

7
Câu trả lời này đã hết hạn, bây giờ bạn có thể đặt giống enumerate(iterable, start=1)như Python 2.6.
Fredrick Brennan

@frb: Bạn đã đọc câu hỏi chưa? Anh ta đã biết giải pháp cho Python 2.6. Ông đặc biệt yêu cầu một giải pháp hoạt động trong Python 2.5.
Mark Byers

1
@MarkByer Rõ ràng tôi bị mù :) Thực sự xin lỗi về điều đó. (Đây là số 1 trong Google cho "liệt kê bắt đầu từ 1")
Fredrick Brennan

2
@ 8chan vâng, tôi vừa mới vào đây từ google tìm kiếm "không liệt kê bắt đầu từ con trăn không" :)
baxx

166

Chỉ cần đặt nó ở đây vì lợi ích của hậu thế, trong 2.6, tham số "bắt đầu" đã được thêm vào để liệt kê như vậy:

enumerate(sequence, start=1)


26
Lưu ý rằng điều này không bỏ qua mục đầu tiên trong danh sách, nó bù chỉ số theo giá trị bắt đầu, do đó bạn sẽ nhận được một mảng ngoài giới hạn nếu bạn đã làm một cái gì đó như: sequence[i]trong mã của bạn.
phyatt

14

Dễ dàng, chỉ cần xác định chức năng của riêng bạn mà làm những gì bạn muốn:

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

12

Con trăn 3

Tài liệu chính thức: enumerate(iterable, start=0)

Vì vậy, bạn sẽ sử dụng nó như thế này:

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

Cách đơn giản nhất để làm trong Python 2.5 chính xác những gì bạn hỏi về:

import itertools as it

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

Nếu bạn muốn một danh sách, như bạn xuất hiện, sử dụng zipthay cho it.izip.

(BTW, như một quy tắc chung, cách tốt nhất để tạo danh sách ra khỏi trình tạo hoặc bất kỳ X lặp lại nào khác là không [x for x in X] , nhưng đúng hơn 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

Bây giờ h = list(enumerate(xrange(2000, 2005), 1))làm việc.


6

liệt kê là không quan trọng, và do đó, thực hiện lại nó để chấp nhận một sự khởi đầu:

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

Lưu ý rằng điều này không phá vỡ mã bằng cách sử dụng liệt kê mà không bắt đầu đối số. Ngoài ra, oneliner này có thể thanh lịch hơn và có thể nhanh hơn, nhưng phá vỡ các cách sử dụng khác của liệt kê:

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

Thứ hai là vô nghĩa. @Duncan có trình bao bọc đúng.


Đúng, vô nghĩa. Một cái gì đó dọc theo các dòng này thực sự sẽ hoạt động trong ví dụ Haskell (currying là điều tự nhiên nhất từng có trong ngôn ngữ đó, và do sự lười biếng của nó, một chức năng lấy một danh sách rất giống với biểu thức của trình tạo). Nhưng điều đó không tha cho tôi - người dùng trăn lâu năm - viết BS. Cảm ơn đã chỉ ra điều đó.

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

liệt kê nên là một máy phát điện. tạo toàn bộ danh sách cùng một lúc chỉ để lặp đi lặp lại nếu thường không được chấp nhận
John La Rooy

Tổng quát hóa: start = 4 danh sách (liệt kê (phạm vi (bắt đầu) + phạm vi (1999, 2005))) [bắt đầu:]
Tony Veijalainen

tuy nhiên phạm vi là danh sách trong 2.52
Tony Veijalainen

3

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


1
Anh ta không thể làm điều này trong Python 2.5. Tham số bắt đầu được giới thiệu trong Python 2.6: docs.python.org/l Library / fiances.html # enum Cả . Ông cũng đề cập đến điều này trong câu hỏi.
Mark Byers

Đã trả lời điều này trước lần chỉnh sửa ban đầu, khi mã không được định dạng và tôi gặp rắc rối là việc sử dụng trình tạo thay vì danh sách.
Chris B.

++: đó là cách để làm điều đó
Nas Banov

2

Ok, tôi cảm thấy một chút ngu ngốc ở đây ... lý do không chỉ làm điều đó với một cái gì đó như thế
[(a+1,b) for (a,b) in enumerate(r)]nào? Nếu bạn không hoạt động, cũng không có vấn đề gì:

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

Vì điều này hơi dài dòng, tôi khuyên bạn nên viết chức năng của riêng mình để khái quát hóa nó:

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

2
liệt kê nên là một máy phát điện. tạo toàn bộ danh sách cùng một lúc chỉ để lặp đi lặp lại nếu thường không được chấp nhận
John La Rooy

0

Tôi không biết làm thế nào những bài viết này có thể được thực hiện phức tạp hơn sau đó:

# Just pass the start argument to enumerate ...
for i,word in enumerate(allWords, 1):
    word2idx[word]=i
    idx2word[i]=word
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.