It's really a bummer that #Python enumerate doesn't have an option to tell it to go backwards.

Also, it took me way too long to figure out that code like this doesn't do what I wanted it to do. (The index doesn't match the location in MyString.)

MyString = "Hello"
for index , Char in enumerate (MyString[::-1]):
print (index, Char)

0 o
1 l
2 l
3 e
4 H

#ScottProgramming #Python3

I did find some proposed solutions that involve reversing a generator function and ... bleh. They may be a little more efficient, but none pleased my eye as much as just reversing the range function, like this:

MyString = "Hello"
for index in range (len(MyString)-1, -1, -1):
print (index, MyString[index])

#Python #Python3 #ScottProgramming

@scottmiller42 That works. Personally I would do this:

reversed(enumerate(MyString))

That could get you in some trouble with memory usage if MyString is really long (like hundreds of millions of characters), but otherwise it's nice and simple.

You could also write your own reverse-enumerate function:

def reverse_enumerate(iterable):
return zip(range(len(iterable), 0, -1), iterable)

although this doesn't work for all iterables, but it will work for strings and lists.

#Python

@diazona

Thanks for the suggestion!

MyString = "Hello"
for index, Char in reversed(enumerate(MyString)):
print (index, Char)

That results in an error:
TypeError: 'enumerate' object is not reversible

The solution I found uses a intermediary list, like this:

MyString = "Hello"
for index, Char in reversed(list(enumerate(MyString))):
print (index, Char)

That code work, but then materializes a copy of the string. And starts to look clunky to me. πŸ™‚

@scottmiller42 Oh, yeah sorry I always forget that step (even in my own coding). Yes, you have to convert it to a list, and yes it does take up memory for that list, but unless the thing you're iterating over (MyString) is really huge, I think it's fine. I mean, yes it's a *little* inelegant, but really not bad IMO.

If you want to work around that, you could write your own reverse enumerate function. Just zip your "reverse range()" with the iterable and return that. Of course that won't work on single-use iterables (like generators, enumerate(), filter(), map(), or so on), but I think there's no way to handle those without storing a copy of their data.

And FWIW you're not wrong that it would be convenient if enumerate() did this itself. But perhaps the fact that you have to choose between (at least) two different implementations depending on what type of iterable you're dealing with is part of why they didn't make it do that.

#Python

@diazona @scottmiller42 i think i would use zip and range, to avoid the downsides of having to copy the list?

for index, char in zip(range(len(my_string), 0, -1), reversed(my_string)):
print(index, char)

@tshirtman @diazona Hah, this is going to make my eyes go wonky at this late hour, but I'll give it a look in daylight. πŸ˜ƒ
@scottmiller42 @tshirtman Yeah no sense losing sleep over it πŸ˜› FWIW this is the cod for the second option I mentioned, so you're still looking at just two alternatives. (I mean, yes there are other ways to do it, but I'm not sure if any of them are as clean as these two)
@diazona @scottmiller42 ah right, I had somehow missed this bit. πŸ˜…

@diazona Aye, and most of the time I'd be using it, the strings are short like for the particular code I'm writing tonight (another LeetCode problem). However, sometimes I try to use them as opportunities to learn how to do something efficient with a bit item, which sometimes I do have to work with very large lists and strings for work.

Thanks again for this productive discussion!

@scottmiller42 Likewise! It's an interesting point that I don't believe I ever really thought about before.