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?
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)
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)]
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)]
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é".
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.
import itertools
def reversed_enumerate(seq):
return itertools.izip(reversed(range(len(seq))), reversed(seq))
Remplacez Zip
par itertools.izip
:)
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))
Utilisez simplement len(lst)-i
partout où i est utilisé. ou:
[(len(range(5)) - x, x) for x in range(5)]