Help with: 'Python 3/Python Code Challenges/Loops/4. Odd Indices'

Here’s the challenge.
I finally solved it but two things still puzzle me.

  1. How/Why does the range function used in the solution automatically refer to the lst list? How is the link made…I don’t get it?
    I mean, in a much more complex algorithm, I can easily imagine possibly needing the range method all over the code so…how do we point the range function to the right portion of our code? Because I don’t see that link in the solution to this problem? Nothing in that range function refers to the lst list, other than using the len(lst) to calculate the length of the list, but that just returns a number used to define the end of our range.

  2. In the solution, they hint to another way of solving this challenge but don’t explain it at all. So I was hoping someone could help here with this:

Another way to do this would be to iterate through all indices and use an if statement to see if the index you’re currently looking at is odd.

That was my whole problem with solving this challenge, both with the original solution and this one…how do you address working with the indices of a list and not their values? Because regardless what I used (loops, conditionals,…) they all used the value of the index and not the index number itself, i.e. it’s position in the list.
Thanks! :wink:

A range object acts as the iterator/iterable in the loop. From this we get a sequence from M to N. These are then usable as index subscripts. We are not looping over the LST as much as looping over the range and using that to orderly access the elements by index, which allows us to mutate any element without disrupting the loop (or corrupting it).

Note that all we want are the values at the odd indices. That means, 1, 3, 5, … We can use the range() function to generate this sequence…

>>> [*range(1, 20, 2)]
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]

This means we don’t have to access every element in the list, just those that our range gives us the indices to.

Now, as for your second question, the author may be hinting at list slicing.

>>> [*range(1, 20)][::2]
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]

To get a sequence of all the even indices we just change the 1 to a zero in the range…

>>> [*range(0, 20)][::2]
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

Thanks mft for the quick and thorough answer! I didn’t expect it to come so quick so I decided to ask my question just before heading for bed. I’ll read it fresh and caffeinated tomorrow morning :wink:.

1 Like

I’m back…your answer to my first question left me confused. This part specifically, I don’t understand:

What is M & N? Where did that come from?
As for better understanding how the range function ‘knows’ it’s working out a range from the lst list…I’m afraid I don’t understand that any better.
But don’t sweat it, sometimes these things just clear themselves up with experience.

As for question number 2…where is the if statement in there?

They are just symbols for ‘start of range’ and ‘end of range’. Both must be integers, and given the sequence is left to right, the lower value is the start, and the higher value, the end.

list(range(-10, 11))

will produce a sequence,

 [-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Now let’s say we have list with 10 items in it, and we want to iterate over every value from left to right, and access by index? Recall that indexes start at 0 on the left.

n = range(len(lst))

for i in n:
    print (lst[i])

Note above that we don’t need to cast the range object to a list. FOR can iterate over the range in its iterator object form.

Ok, got it for the M and N (is that a convention?).
However, I don’t quite understand why you are explaining what comes after in your reply? That’s not relevant to my question?

A lot of explanations employ symbols as stand-in values. M and N are just arbitrary symbols, nothing to do with convention.

M = -10
N = 11
n = range(M, N)

Now they are actual variables, but refer to the assigned values.

As for the IF statement, there is none required. The parameters of the range function set out, the starting index, the excluded ending index, and in the earlier case, the step or stride value (2). When using the stride we no longer need to check if an index is odd or even. We know where they are, and how far apart each is from the next one.

If we’re still missing something here, point it out, please.

Well, as I said, I was just curious what is the other solution Codecademy wrote was available using the if statement. You’re making the point that it’s not necessary, while I’m trying to figure out how to in fact use that if statement, even if can be solved without it (as is the case with the first solution).

We can use an if statement, yes, to check if the index is odd or even:

lst = [3, 6, 9, 23, 34, 45, 67, 80, 89, 91]
n = range(len(lst))

for i in n:
    if i % 2 == 1:
        print (lst[i])


Notice that the output corresponds with the values at odd indexes.

Yup, that definitely works! Thanks :slightly_smiling_face:

1 Like