15/15 Median - Why does this code return the error code "list index out of range"


#1

https://www.codecademy.com/courses/python-intermediate-en-rCQKw/2/5
Why does this code return the error code "list index out of range"

    def median(list1):
        sort = sorted(list1) #Sorts the list
        result = 0
        for x in sort:
            if len(sort) % 2 == 0:
                #If even amount of items in list
                result = result + sort[((sort[len(sort)/2]) + (sort[len(sort) / 2 - 1])) / 2]
            else:
                #If uneven amount of items in list
                result = result + sort[(len(sort) / 2)]
        return result

#2

Take a look at this line, which is similar to what you did, with a few less brackets:

print (sort[len(sort)/2] + sort[len(sort)/2 -1 ]) / 2

this will print 4. Your items are indexed at 0,1,2,3. So, there is no index 4. This:

((sort[len(sort)/2]) + (sort[len(sort) / 2 - 1])) / 2

will calculate the average, which is 4.5, but since you have integers only, it will show 4. You might want to change this into a float. So, no need to do:

result = result + sort[ /* code of above */ ]

you don't need to access index of sort, it will return to you the average of the two numbers, not the index


15. Median
#3

I see this as a case of too much repetition, which is generally a signal that things can be simplified, starting with len(sort).

We also need to determine if the inputs are literal, or an object. If we are certain that the parameter is a list literal, then we don't need a copy of the list. We can sort the parameter list in place.

def median(sample_space):
    n = len(sample_space)         # take the length only once
    if n < 1:
        return 0                  # or False for empty list
    if n < 2:
        return sample_space[0]    # value in element is the median
    sample_space.sort()           # sort in place

In the above example we take two basic steps and the problem is nearly solved. The list is sorted in place, and the length is assigned to n.

If n is odd, our job is almost complete. We need only the integer quotient of n / 2 to determine the index of the median in the sorted list.

m = n / 2
if n % 2 != 0:
    return sample_space[m]

Now we can work with n being even. The median will be the average (mean) of the two middle elements. What are their indices? m and m-1

    return float(sample_space[m] + sample_space[m-1]) / 2

Putting it all together, we have eleven lines of simple code.

def median(sample_space):
    n = len(sample_space)
    if n < 1:
        return 0
    if n < 2:
        return sample_space[0]
    sample_space.sort()
    m = n / 2
    if n % 2 != 0:
        return sample_space[m]
    return float(sample_space[m] + sample_space[m-1]) / 2

The above not meant as a solution, only an example of how things can be kept simple.


#4

We can further simplify this by first shortening the variable, and combining the two last return statements into a single ternary expression:

    # let s = sample_space in this example

    return s[m] if n % 2 != 0 else (s[m] + s[m - 1]) / 2.

Gotta love Python!


#5

I too am experiencing this issue. I tested each equation in my Python interpreter...

def median(x):
    y = sorted(x)
    median_even = y[len(y) / 2 + 1] + y[len(y) / 2 - 1] / 2.0 
    median_odd = y[len(y) - (len(y) -1 / 2 - 1)]
    if len(y) == 1:
        return y[0]
    elif len(y) % 2 == 0:
        return median_even
    else: 
        return median_odd

#6

what is the error message? Codecademy uses python2.7.3, what version are you using? There are some difference between 2 and 3


#7

Oops, try again. median([1]) resulted in an error: list index out of range


#8

I am testing in 2.7.5 on OS X 10.9.5


#9
>>> x = [2,2,4,4]
>>> y = sorted(x)
>>> y[len(y) / 2 + 1] + y[len(y) / 2 - 1] / 2.0
5.0
>>> x = [1,2,3]
>>> y[len(y) - (len(y) -1 / 2 - 1)]
2
>>> x = [1]
>>> y[0]
2
>>> y = sorted(x)
>>> y[0]
1

#10

if you have this line:

median_odd = y[len(y) - (len(y) -1 / 2 - 1)]

you would need to check if the list is one in length as first