15. Median


#1



https://www.codecademy.com/courses/python-intermediate-en-rCQKw/2/5?curriculum_id=4f89dab3d788890003000096#

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

This is the first exercise in the practice section that I've been able to get so far in w/o consulting the Q&A, which is fun. But now I'm really stuck. I used print to test throughout, and I know it's getting as far as the the if/elif/else statements, but then I get hung up on why it fails on getting the average.


# define numlist
    
def median(numlist):
     
    # sort the sequence numerically, using sorted()
    sortedlist = sorted(numlist)
    
    # count the number of values 
    num = len(sortedlist)

    if num == 1:
        average = 1.0
        return average
        
    # check if num is even...
    elif num % 2 == 0:
        # locate the middle two values
        middle_a = num / 2
        # for a list [0,1,1,2,3,4] has num 6, so 6/3 = 2, so middle_a would be 2.
        
        middleindex_a = sortedlist[middle_a]

        middle_b = middleindex_a + 1
        middleindex_b = sortedlist[middle_b]
    
        average = ((middleindex_a + middleindex_b) / 2.0)
        return average
    
    # if num is odd...
    else:
        # locate the middle value
        middle = num / 2
        middleindex = sortedlist[middle]
        average = (middleindex / 2.0)
        return average
    return average
print median(numlist)


#2

A median is not an average. num is the length, not the value. A median is a value in the middle of the data. We don't have to check for a unit length since it will be sussed out in the odd length condition.


#3

Traceback (most recent call last):
  File "median.py", line 37, in <module>
    print median([4, 5, 5, 4])
  File "median.py", line 22, in median
    middleindex_b = sortedlist[middle_b]
IndexError: list index out of range

This message is the next thing to consider.
It tells you the line where the exception occurs, together with the code on that line and the message of the exception you can conclude that middle_b isn't a valid index for sortedlist - next you'd then consider the length of sortedlist and the value of middle_b (by printing) - figure out which one is the offender, and how it obtained that value


#5

here is the way you can check if len is not even:...

if len(nlist)%2!=0:
    med=nlist[int((len(nlist)-1)/2)]
    print ('Median: ', med)
    return(med)

and here is the workaround if len is even

else:
    #median is in between of L index and H index: exp list [1,2,3,4] ,  med=2.5 
    #L - is low median
    #H - is high media
    L=int((len(nlist)/2)-1)
    print ('L index - ', L)
    print ('L item - ', nlist[L])
    H=int((len(nlist)/2))
    print ('H index- ', H)
    print ('H item - ', nlist[H])

    med=(float(int(nlist[L])+int(nlist[H])))/2
    print ('Median: ', med)
    return (med)

#6

I got it!! Not a ton of changes needed:
I did change all references from average to median -- that was a dumb mistake on my part
I'm not quite sure what was happening in the even leg, but I added a bunch of print statements and defined numlist to test with different values.
The odd leg was the biggest problem, though: median is not the middle value / 2.0 , it's just the middle value!

Final code below, with extra prints and comments removed.

    
def median(numlist):
     
    sortedlist = sorted(numlist)
    num = len(sortedlist)    
    
    if num % 2 == 0:
        # locate the index of the middle two values
        middle_a = num / 2
        middleindex_a = sortedlist[middle_a]
        
        middle_b = middle_a - 1
        middleindex_b = sortedlist[middle_b]
       
        median = ((middleindex_a + middleindex_b) / 2.0)
        return median
    
    # if num is odd...
    else:
        # locate the middle value
        middle = num / 2
        median = sortedlist[middle]
        return median

    return median

print median(numlist)

#7

Now you're going to hate me when you see how simple this problem is...


def median(x):
    s = sorted(x)
    n = len(s)
    m = int(n / 2)
    if n % 2: return s[m]
    return float(s[m - 1] + s[m]) / 2

This is not to show off, but to stress the importance of refactoring. Simplify, reduce, simplify, reduce. It takes practice, and some determination to drill down to the lowest common denominator, so to speak.


#8

OMG

OMG!!
The code above is brief and accurate.
can't believe I spent so many lines and minutes on same task........nice to know.
kindly explain this line and how it works
if n % 2: return s[m


#9

When n is odd, and because we use if, n % 2 will be 1 which casts to True. The action is to return the value of the middle element.

The expression relies on the interpreter to cast a boolean from a number. A non-zero number is truthy, and zero (0) is falsy. Any value that is truthy will cast to True.


#10

no hate here! Totally appreciate the feedback, thanks!

Is the n % 2 expression the same as if n % 2 == 0 ?

eta: nevermind, just got what your explanation above was saying.


#11

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.