2016-08-03 15 views
8

Tôi đang cố đảo ngược chỉ mục được đưa ra bởi enumerate trong khi giữ lại thứ tự ban đầu của danh sách được liệt kê.Python liệt kê chỉ số đảo ngược chỉ

Giả sử tôi có như sau:

>> range(5) 
[0, 1, 2, 3, 4] 

Nếu tôi liệt kê này tôi sẽ nhận được như sau:

>> list(enumerate(range(5))) 
[(0, 0), (1, 1), (2, 2), (3, 3), (4, 4)] 

Tuy nhiên tôi muốn đảo ngược chỉ số được cung cấp bởi enumerate vì vậy mà tôi nhận được:

[(4, 0), (3, 1), (2, 2), (1, 3), (0, 4)] 

Cho đến nay tôi có mã sau:

reversed(list(enumerate(reversed(range(5))))) 

Tôi đã tự hỏi liệu có cách nào để làm điều này không?

Trả lời

9

Làm thế nào về việc sử dụng mã zip thay vì một phạm vi đảo ngược?

>>> zip(range(9, -1, -1), range(10)) 
[(9, 0), (8, 1), (7, 2), (6, 3), (5, 4), (4, 5), (3, 6), (2, 7), (1, 8), (0, 9)] 


>>> def reversedEnumerate(l): 
     return zip(range(len(l)-1, -1, -1), l) 
>>> reversedEnumerate(range(10)) 
[(9, 0), (8, 1), (7, 2), (6, 3), (5, 4), (4, 5), (3, 6), (2, 7), (1, 8), (0, 9)] 

Như @julienSpronk cho thấy, sử dụng izip để có được một máy phát điện, cũng xrange:

import itertools 
>>> import itertools 
>>> def reversedEnumerate(l): 
...  return itertools.izip(xrange(len(l)-1, -1, -1), l) 
...  
>>> reversedEnumerate(range(10)) 
<itertools.izip object at 0x03749760> 
>>> for i in reversedEnumerate(range(10)): 
...  print i 
...  
(9, 0) 
(8, 1) 
(7, 2) 
(6, 3) 
(5, 4) 
(4, 5) 
(3, 6) 
(2, 7) 
(1, 8) 
(0, 9) 
+0

Cũng là một ý tưởng hay. – RemcoGerlich

+0

hoặc 'itertools.izip' để nhận máy phát điện –

+0

Cảm ơn! Tôi luôn quên về zip! – rozzy

2

Chỉ cần chiều dài của danh sách của bạn và trừ các chỉ số từ đó ...

L = range(5) 

for i, n in L: 
    my_i = len(L) -1 - i 
    ... 

Hoặc nếu bạn thực sự cần một máy phát điện:

def reverse_enumerate(L): 
    # Only works on things that have a len() 
    l = len(L) 
    for i, n in enumerate(L): 
     yield l-i-1, n 

enumerate() không thể nào làm được điều này, vì nó hoạt động với các trình vòng lặp chung. Ví dụ, bạn có thể vượt qua nó vòng lặp vô hạn, mà thậm chí không có một "chỉ số đảo ngược".

4

Tôi không biết nếu giải pháp này là tốt hơn cho bạn, nhưng ít nhất nó ngắn:

>>> [(4 - x, x) for x in range(5)] 
[(4, 0), (3, 1), (2, 2), (1, 3), (0, 4)] 
2

Giả sử danh sách của bạn không dài và bạn sẽ không gặp phải lỗi hiệu suất, bạn có thể sử dụng list(enumerate(range(5)[::-1]))[::-1].

Test:

>>> list(enumerate(range(5)[::-1]))[::-1] [(0, 4), (1, 3), (2, 2), (3, 1), (4, 0)]

+0

xin vui lòng, đọc kỹ những gì anh ta yêu cầu – Netwave

+0

Tôi đã cung cấp cách thức gọn gàng nhất để làm điều này như tôi đã hiểu. Tuy nhiên, câu hỏi này là loại hương vị. – user3036878

+0

anh ấy muốn các chỉ mục bị đảo ngược, không phải danh sách – Netwave

2

Thật sự tôi đang sử dụng cùng một logic như @RemcoGerlich đã làm, nhưng tôi sử dụng list comprehension trực tiếp, mà làm cho mã ngay bây giờ trở thành 1-liner:

def generatelist(x): 
    return [(x-1-i,n) for i,n in enumerate(range(x))] 

Về tình huống khó xử khi chọn generator hoặc list comprehension, here là cách được đề xuất:

Về cơ bản, hãy sử dụng biểu thức trình tạo nếu tất cả những gì bạn đang làm đang lặp lại một lần. Nếu bạn muốn lưu trữ và sử dụng các kết quả được tạo ra, thì bạn có thể tốt hơn với một danh sách hiểu.

0

Nếu bạn đang đi để tái sử dụng nó nhiều lần, bạn có thể làm cho máy phát điện riêng bạn:

def reverse_enum(lst): 
    for j, item in enumerate(lst): 
     yield len(lst)-1-j, item 

print list(reverse_enum(range(5))) 
# [(4, 0), (3, 1), (2, 2), (1, 3), (0, 4)] 

hoặc

def reverse_enum(lst): 
    return ((len(lst)-1-j, item) for j, item in enumerate(lst)) 
0

Đơn giản chỉ cần sử dụng len(lst)-i ở khắp mọi nơi tôi được sử dụng. hoặc:

[(len(range(5)) - x, x) for x in range(5)] 
Các vấn đề liên quan