Can I use `index()` for the loop challenge?

the solution to this challenge was quite straight forward, but i did it the stupid way using .index():

#Write your function here
def odd_indices(lst):
  new_lst = []
  for item in lst:
      if lst.index(item)%2==1:
        new_lst.append(item)
  return new_lst

#Uncomment the line below when your function is done
print(odd_indices([4, 3, 7, 10, 11, -2]))
5 Likes

No way is ‘stupid’ though some do come with provisos and gotchas. list.index() has one of its own. What if there are duplicates in the list? .index() will only ever find the first one. In this exercise we wouldn’t need to know the index in this way.

We know that a list has a sequential index starting at 0. Zero is even so we would want to start one space over, with 1. Next we go to 3, then 5, then 7, and so on, in steps of 2. Sounds like a job for range since it can be started and stopped anywhere, and we can step in any stride length.

range(1, len(lst), 2)

After that it’s just a matter of appending the value at the current index to the return list. No if's about it.

11 Likes

when you look at it from that perspective , it makes complete sense!
much love for the detailed explanation <3

1 Like

Hi is there a way to check what position an index has in a list? i was trying to do it with %2 != 0 method

We can use the .index() method if we are sure there is but one item, and no duplicates since this method will only return the index of the first item it finds.

>>> a = [2,5,8,9,3,2,5,8]
>>> a.index(8)
2
>>> 

Unless we spin off a shortened slice, we will not get to the other 8.

>>> b = a[a.index(8)+1:]
>>> b.index(8)
4
>>> 

We do have a tool that we can use to find all the indices, but it will take some reckoning…

>>> c = [i for i, x in enumerate(a) if x == 8] # i is the index, x the item
>>> c
[2, 7]
>>> 
1 Like
def odd_indices(lst):
  return [elem for elem in lst if lst.index(elem) % 2 != 0]

If I do it this way will it not also cover the edge cases like when there are 2 same elements?

Never mind. It’s basically the same thing as the example that started this thread and I think I understand the problem now. The range function makes more sense in this case. Thank you!

I just recently starting using these help/question things and my god. I would just like to say that this mtf guy is SOOOOO HELPFUL! Without this guy I would be in a state ‘vexation’
Sometimes I feel like they just throw you in some deep waters after guiding you in the shallow end. But thank you mtf guy! I was ready to give up in frustration but knowing there’s accecible help to guide me through the complicated parts is very helpful,

2 Likes

I’m not quite sure that this is true in <for – in> example:

What if there are duplicates in the list? .index() will only ever find the first one.

i wrote:

def odd_indices(lst):
  new_list = [new_index for new_index in lst if lst.index(new_index) % 2 == 1]
  return new_list

and it worked just fine with sequences like [4, 3, 7, 10, 11, -2] or (with dublicates) [4, 3, 7, 3, 11, -2]
Or am i just not seeing something important?

Python List index() returns smallest index of element in list

Consider,

>>> u = [1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9]
>>> [x for x in u if u.index(x) % 2 == 1]
[2, 4, 6, 8, 2, 4, 6, 8]
>>> 

What should be in the return list?

[1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9]
   ^   ^   ^   ^   ^   ^   ^   ^   ^

The error is caused by using .index().

Now consider,

>>> [u[x] for x in range(1, len(u), 2)]
[2, 4, 6, 8, 1, 3, 5, 7, 9]
>>> 

So why then it skips 9-th idex? 10-th idex isn’t the smallest. What i see is that for some reason it has “odd” behaviour with odd numbers. For examle if we replace first 4 with 7 it’ll output [2, 7, 6, 7, 8, 2, 6, 7, 8] and now it includes 6-th idex still excludes 9-th index, exludes 11, 12, 13-th and 17-th indexes.
Sorry, i am very confused right now, i can’t help it with this issue )

The first error there is caused by index the second time the value 1 appears which as you correctly state is the 9th index. So what happens in the if expression used in our comprehension:

if u.index(x) % 2 == 1

So what does u.index(x) actually evaluate to for index [9]? Since the value at index 9 is an integer 1 we have u.index(1). Print it and see but you’ll find it equals 0. Does 0 % 2 == 1? No it does not. So we skip this value despite the fact it’s actually in a position we wanted to return. That’s a problem. This problem continues with further elements of the list.

A blunt example of index only returning the first matching element-

# idx=( 0    1    2    3    4    5 )  # Included only to show the index of the list.
lst = ['a', 'b', 'a', 'b', 'a', 'b'].index('b')  #
# .index('b') will only ever supply an index of 1
# we can only find the first appearance using just .index()

Using just .index we have completely ignored the values of ‘b’ at index 3 and and index 5.

1 Like

Ok, i think i understand it now. Even if there are other flaws that came up with changing 4 with 7.
Think i need to come back here another time.
Anyways, Thank You for the explanation !

1 Like