web-dev-qa-db-fra.com

Python énumère uniquement les index inversés

J'essaie d'inverser l'index donné par enumerate tout en conservant l'ordre d'origine de la liste énumérée.

Supposons que j'ai les éléments suivants:

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

Si j'énumère ceci, j'obtiendrais ce qui suit:

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

Cependant, je veux inverser l'index fourni par enumerate afin d'obtenir:

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

Jusqu'à présent, j'ai le code suivant:

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

Je me demandais s'il y avait une manière plus ordonnée de faire cela?

10
rozzy

Que diriez-vous d'utiliser Zip à la place avec une plage inversée?

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

Comme @julienSpronk le suggère, utilisez izip pour obtenir un générateur, également 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)
11
Netwave

Je ne sais pas si cette solution est meilleure pour vous, mais au moins, elle est plus courte:

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

En supposant que votre liste ne soit pas longue et que vous ne rencontriez pas d'erreur de performance, vous pouvez utiliser list(enumerate(range(5)[::-1]))[::-1].

Tester:

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

3
Emil

Prenez simplement la longueur de votre liste et soustrayez l'index de celui-ci ...

L = range(5)

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

Ou si vous avez vraiment besoin d'un générateur:

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() ne peut pas le faire, car cela fonctionne avec des itérateurs génériques. Par exemple, vous pouvez lui transmettre des itérateurs infinis, qui n'ont même pas un "index inversé".

3
RemcoGerlich

En fait, j'utilise la même logique que celle utilisée par @RemcoGerlich, mais j'utilise directement list comprehension, ce qui fait que le code devient désormais une ligne:

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

En ce qui concerne le dilemme de choisir generator ou list comprehension, ici est le moyen suggéré:

Fondamentalement, utilisez une expression génératrice si vous ne faites qu’itérer une fois. Si vous souhaitez stocker et utiliser les résultats générés, vous avez probablement intérêt à utiliser une liste de compréhension.

2
MaThMaX

Python 2

import itertools

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

Python 3

Remplacez Zip par itertools.izip :)

0
tzot

Si vous comptez le réutiliser plusieurs fois, vous pouvez créer votre propre générateur:

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

ou

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

Utilisez simplement len(lst)-i partout où i est utilisé. ou:

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