Python Python Collections Slices Slice Functions

Daniele Santos
Daniele Santos
14,279 Points

What's wrong with my code?

I don't understand why my reverse_evens function doesn't work. All I get from the tests is "Try again" which leaves me no hint...

slices.py
def first_4(iterable):
    return iterable[0:4]    

def first_and_last_4(iterable):
    return iterable[0:4] + iterable[-4:]    

def odds(iterable):
    return iterable[1::2]

def reverse_evens(iterable):
    iterable = iterable[::2]
    iterable.sort(reverse = True)
    return iterable

4 Answers

Michael Cook
Michael Cook
12,742 Points

Hey Daniele, this one is tricky. Try breaking each step down with comments or on a notepad first. First, what is the challenge really asking of you? Can you clearly state it? Here's how I would state it:

"Create a function that takes a single argument that is an iterable, and returns a slice of that iterable containing only members of the argument occupying an index position with an even number, and presents them in the reverse order."

If we operate on that definition of the problem, then it must follow logically that we need the length of the iterable passed to the function, since the index position that the slice starts at will depend on whether the last item in the iterable occupies an odd or even index position, and this depends on the length of the iterable.

So first, get the length of the iterable.

Then, you need to determine which index value to start your slice from: the last index value (-1), or the second last (-2) since depending on the length of the iterable, either one could be the last even index position. This will take a bit of thinking and a bit of basic math. Also, Google is your friend.

Finally, once you have determined which index position to begin your slice at, last or second-last index position, you can set up a conditional that will return two different slices depending on whether the last index position is even or odd.

I hope I haven't confused you. Re-read my answer a few times if necessary and feel free to ask me to clarify. This is a deceptively tricky challenge and I wanted to get you thinking along the right lines to solve it rather than giving the answer. Good luck!

Daniele Santos
Daniele Santos
14,279 Points

Thanks for taking the time to review my answer, Michael! I thought of something along these lines. What do you think?

def reverse_evens(iterable):
    if len(iterable) % 2 == 0:
        return iterable[2::2][::-1]
    else:
        return iterable[::2][::-1]
Michael Cook
Michael Cook
12,742 Points

It's been about 10 days since I solved that particular challenge and unless I sit down and re-do it I won't know exactly what my code was. However I can say that now your thinking is defining on the right track. However in your else-statement you have a slice of a slice, and that isn't right. Also, something that really tripped me up at first is remembering that the length of an iterable by itself will not tell you whether any particular item in the iterable has an odd or even index value. This is because Python assigns index values starting from 0 rather than 1. So consider a list ls = [1, 2, 3, 4, 5]. If you get the length of ls by using len(ls) it will return 5. But since index values start at 0, the index position of the last item in ls is 4. So remembering this is key for your function too. Kenneth was trying to trip people up a bit ;)

Daniele Santos
Daniele Santos
14,279 Points

Somehow it passes the tests if we just run:

def reverse_evens(iterable):
        return iterable[::2][::-1]
Michael Cook
Michael Cook
12,742 Points

Interesting. Well congrats, you found a more efficient way to solve the problem!

Daniele Santos
Daniele Santos
14,279 Points

Michael Cook, Not sure it's the best answer, but somehow it worked. Anyway, thanks for helping! I really appreciate that! :)

Robert Carter
Robert Carter
828 Points

I was able to get it with

def reverse_evens(iterable):
    iterable = iterable[::2]
    return iterable[::-1]