Median code explanation

G.G picture G.G · Sep 28, 2011 · Viewed 23.2k times · Source

My professor wrote this median function and I don't understand it very well. Can someone please explain the part about i = len(list)/2 and median = avg() and the else statement?

def avg_list(numbers):  
    sum = 0 
    for num in numbers:
        sum += num

    avg = float(sum)/len(numbers)
    print avg

def median(list):            
    list.sort()
    if len(list)%2 == 0:
        #have to take avg of middle two
        i = len(list)/2
        median = avg()
    else:
        #find the middle (remembering that lists start at 0)
        i = len(list)/2
        median = list        
    return median

To add from an example I saw, for even list length:

def median(s):
    i = len(s)
    if not i%2:
        return (s[(i/2)-1]+s[i/2])/2.0
    return s[i/2]

This works very well but I don't understand the last return s[i/2]?

For odd list length:

x = [1,2,5,2,3,763,234,23,1,234,21,3,2134,23,54]
median = sorted(x)[len(x)/2]

Since x has a list length of odd, wouldn't the [len(x)/2] be a floating number index? I'm not getting this all the way? Any explanation better than mine is much appreciated.

Answer

NullUserException picture NullUserException · Sep 28, 2011

Why this is is very wrong, line by line:

def median(list):              # 1

    list.sort()                # 2

        if len(list)%2 == 0:   
        #have to take avg of middle two
            i = len(list)/2    # 3
            median = avg()     # 4
        else:
            #find the middle (remembering that lists start at 0)
            i = len(list)/2    # 5
            median = list      # 6

        return median

#1: It's a bad idea to give your variables the same name as data types, namely list.

#2: list.sort() will modify the list that is being passed. One would expect a getter like median() not to do that.

#4 It calls a function avg() with no arguments, which is completely meaningless, even if such a function was defined.

#3 and #5 are calculated the same way regardless of the if branch taken. Regardless, i is never used.

#6 It sets median to the original list, which makes zero sense.


Here's how I would rewrite this (while maintaining clarity):

def median(alist):

    srtd = sorted(alist) # returns a sorted copy
    mid = len(alist)/2   # remember that integer division truncates

    if len(alist) % 2 == 0:  # take the avg of middle two
        return (srtd[mid-1] + srtd[mid]) / 2.0
    else:
        return srtd[mid]

Also, the avg_list() function (which is not used nor could be used in median()) could be rewritten as:

def avg_list(numbers):  
    return float(sum(numbers))/len(numbers)

sum() is a function that returns the sum of all elements in an iterable.