Python перечисляет только обратный индекс

Я пытаюсь изменить индекс, заданный enumerate, сохраняя при этом исходный порядок перечисляемого списка.

Предположим, у меня есть следующее:

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

Если я перечислю это, я получу следующее:

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

Однако я хочу изменить индекс, предоставленный enumerate, чтобы получить:

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

Пока у меня есть следующий код:

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

Мне просто интересно, есть ли более аккуратный способ сделать это?


person rozzy    schedule 03.08.2016    source источник


Ответы (10)


Как насчет использования zip вместо обратного диапазона?

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

Как предлагает @julienSpronk, используйте izip, чтобы получить генератор, а также 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)
person Netwave    schedule 03.08.2016
comment
или itertools.izip чтобы получить генератор - person Julien Spronck; 03.08.2016

Я не знаю, лучше ли это решение для вас, но, по крайней мере, оно короче:

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

Просто возьмите длину вашего списка и вычтите индекс из этого...

L = range(5)

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

Или, если вам действительно нужен генератор:

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() не может этого сделать, так как работает с универсальными итераторами. Например, вы можете передать ему бесконечные итераторы, у которых даже нет «обратного индекса».

person RemcoGerlich    schedule 03.08.2016

Предполагая, что ваш список не длинный и вы не столкнетесь с ошибками производительности, вы можете использовать list(enumerate(range(5)[::-1]))[::-1].

Контрольная работа:

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

person Emil    schedule 03.08.2016
comment
Я предоставил самый аккуратный способ сделать это, как я понял. Впрочем, это вопрос вкусовщины. - person Emil; 03.08.2016
comment
он хочет, чтобы индексы были перевернуты, а не список - person Netwave; 03.08.2016
comment
Ой! Верно. исправлено. - person Emil; 03.08.2016
comment
Это то, что я бы сделал также. Лично меня бы даже не заботил последний реверс... - person zwep; 21.06.2018

На самом деле я использую ту же логику, что и @RemcoGerlich, но я использую list comprehension напрямую, что делает код теперь однострочным:

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

Что касается дилеммы выбора generator или list comprehension, здесь предлагается способ:

По сути, используйте выражение генератора, если все, что вы делаете, это итерация один раз. Если вы хотите хранить и использовать сгенерированные результаты, вам, вероятно, лучше использовать понимание списка.

person MaThMaX    schedule 03.08.2016

Если вы собираетесь использовать его несколько раз, вы можете сделать свой собственный генератор:

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

or

def reverse_enum(lst):
    return ((len(lst)-1-j, item) for j, item in enumerate(lst))
person Julien Spronck    schedule 03.08.2016

Просто используйте len(lst)-i везде, где используется i. или:

[(len(range(5)) - x, x) for x in range(5)]
person John    schedule 17.03.2017

Питон 2

import itertools

def reversed_enumerate(seq):
    return itertools.izip(reversed(range(len(seq))), reversed(seq))

Питон 3

Замените zip на itertools.izip :)

person tzot    schedule 13.11.2018

values = 'abcde'

for i, value in zip(reversed(range(len(values))), values):
    print(i, value)

Объяснение:

values = 'abcde'

values_len = len(values) # 5
indexes = range(values_len) # [0, 1, 2, 3, 4]
reversed_indexes = reversed(indexes) # [4, 3, 2, 1, 0]

# combine reversed indexes and values
reversed_enumerator = zip(reversed_indexes, values)

for i, value in reversed_enumerator:
    print(i, value)
person alexfv    schedule 04.04.2019
comment
Пожалуйста, опишите, что вы изменили и почему, чтобы помочь другим определить проблему и понять этот ответ. - person FZs; 04.04.2019

Мы можем использовать перечисление с len:

$ cat enumerate.py 


arr = ['stone', 'cold', 'steve', 'austin']
for i, val in enumerate(arr):
    print ("enu {} val {}".format(i, val))
for i, val in enumerate(arr):
    print ("enu {} val {}".format(len(arr) - i - 1, val))
$  python enumerate.py 
enu 0 val stone
enu 1 val cold
enu 2 val steve
enu 3 val austin
enu 3 val stone
enu 2 val cold
enu 1 val steve
enu 0 val austin
$  
person Venfah Nazir    schedule 23.08.2019