2016-08-03 10 views
8

Próbuję odwrócić indeks podany przez enumerate, zachowując przy tym pierwotną kolejność wyliczanej listy.Wyliczenie tylko indeksu odwróconego w języku Python

Przyjmijmy, mam następujące:

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

Gdybym wyliczyć to chciałbym uzyskać następujące:

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

Jednak chcę odwrócić indeksu dostarczone przez enumerate, tak aby uzyskać:

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

Do tej pory mam następujący kod:

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

Zastanawiam się, czy nie było na to lepszego sposobu?

Odpowiedz

9

Co powiesz na używanie zip zamiast odwróconego zakresu?

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

Jak sugeruje @julienSpronk użyć izip uzyskać generator, także 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

Również fajny pomysł. – RemcoGerlich

+0

lub 'itertools.izip', aby uzyskać generator –

+0

Dzięki! Zawsze zapominam o zipie! – rozzy

2

Wystarczy wziąć długość listy i odejmowanie indeks z tym, że ...

L = range(5) 

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

Lub jeśli naprawdę potrzebujesz generator:

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() nie sposób to zrobić, ponieważ działa z ogólnymi iteratorami. Na przykład możesz przekazać to nieskończone iteratory, które nie mają nawet "odwróconego indeksu".

4

ja nie wiem, czy to rozwiązanie jest dla was lepsze, ale przynajmniej jest krótszy:

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

Zakładając, że lista nie będzie długa i nie wystąpią błędy wydajności, można użyć list(enumerate(range(5)[::-1]))[::-1].

Test:

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

+0

proszę, przeczytaj uważnie, o co prosi – Netwave

+0

Podałem najmodniejszy sposób robienia tego, co zrozumiałem. Jednak to pytanie jest rodzaju smaku. – user3036878

+0

chce, aby indeksy zostały odwrócone, a nie lista – Netwave

2

Właściwie używam tej samej logiki jak zrobił @RemcoGerlich, ale używam list comprehension bezpośrednio, które sprawiają, że kod teraz stać 1-liner:

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

W odniesieniu do dylematu wyboru generator lub list comprehension, here jest sugerowany sposób:

Zasadniczo, użyj wyrażenia generatora, jeśli wszystko, co robisz, to iterowanie raz. Jeśli chcesz przechowywać wygenerowane wyniki i korzystać z nich, prawdopodobnie lepiej spisujesz się ze zrozumieniem listy.

0

Jeśli masz zamiar użyć go ponownie kilka razy, można zrobić własny generator:

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

lub

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

Wystarczy użyć len(lst)-i wszędzie i jest używany. lub:

[(len(range(5)) - x, x) for x in range(5)]