views:

6223

answers:

3

In my example code below, is the counter = 0 really required, or is there a better, more Python, way to get access to a loop counter? I saw a few PEPs related to loop counters, but they were either deferred or rejected (PEP 212 and PEP 281).

This is a simplified example of my problem. In my real application this is done with graphics and the whole menu has to be repainted each frame. But this demonstrates it in a simple text way that is easy to reproduce.

Maybe I should also add that I'm using Python 2.5, although I'm still interested if there is a way specific to 2.6 or higher.

# Draw all the options, but highlight the selected index
def draw_menu(options, selected_index):
    counter = 0
    for option in options:
        if counter == selected_index:
            print " [*] %s" % option
        else:
            print " [ ] %s" % option
        counter += 1


options = ['Option 0', 'Option 1', 'Option 2', 'Option 3']

draw_menu(option, 2) # Draw menu with "Option2" selected

When run, it outputs:

 [ ] Option 0
 [ ] Option 1
 [*] Option 2
 [ ] Option 3
+25  A: 

Use enumerate() like so:

def draw_menu(options, selected_index):
    for (counter, option) in enumerate(options):
        if counter == selected_index:
            print " [*] %s" % option
        else:
            print " [ ] %s" % option    

options = ['Option 0', 'Option 1', 'Option 2', 'Option 3']
draw_menu(options, 2)
Evan Fosmark
The parens around `(counter, option)` aren't necessary and are usually omitted.
Adam Rosenfield
True. I added parenthesis because it makes more clear for me, but maybe others feel differently.
Evan Fosmark
+1  A: 

You could also do:

 for option in options:
      if option == options[selected_index]:
           #print
      else:
           #print

Although you'd run into issues if there are duplicate options.

thedz
Or if options is an iterator.
Glenn Maynard
+1  A: 

I'll sometimes do this:

def draw_menu(options, selected_index):
    for i in range(len(options)):
        if i == selected_index:
            print " [*] %s" % options[i]
        else:
            print " [ ] %s" % options[i]

Though I tend to avoid this if it means I'll be saying options[i] more than a couple of times.

Laurence Gonsalves
In such a case you should always use enumerate()
Georg
gs, what if you only need to get the element every once in a while, but you need the index every time? It seems like in those situations this could be beneficial because you aren't creating a new variable each time.
Evan Fosmark
@gs: yes. That answer was already posted though, so I was posting an alternate solution. As usual, which answer is best depends on the details of your situation.
Laurence Gonsalves