Recall that for an odd length list, there are equal number of elements on either side of the median…
[1][2][3] [4] [5][6][7] => sorted list
^
median == 4
and for even length lists to balance out the same way, we need a pair of elements as the median…
[1][2][3] [4][5] [6][7][8] => sorted list
^
median == float(4 + 5) / 2
One goal of simplification is reduction and ellimination of repetition.
Your first line in the earlier example is an good first step… Cache the length. For simplicity we can use n
as our variable (it’s less verbose).
Unfortunately it’s beyond that point that things come off the rails by overcomplicating the problem.
Given a list, we’ll call it, sample
, our first step is to sort it, which we cache as a separate list so as not to modify the original order, along with the length.
s = sorted(sample)
n = len(s)
I used simple variable names because their definitions are very clear, and right in the code. We have only to look up and see what values they represent without going into verbose detail.
Finding the middle of the list involves simple integer division…
m = n // 2
Consider a list with length 1. What will m
be? Answer, 0
. This means we do not have to test if the length is one, just return the value at that index… s[0]
. This still does not take an extra step as it fits right into the pattern of any odd length list median.
if n % 2: return s[m] # read as `if n MOD 2 is non-zero`
So in four lines of simple code we have returned the median for all odd length lists.
The final step will involve only even length lists. Here is where we need to take a careful look at the value of m
.
0 1 2 3 4 5 6 7 => indexes
[1][2][3] [4][5] [6][7][8]
^
median
What is the value of m
for the above list?
8 // 2 => 4
Now look where index 4 is in the above? It is the right side of the middle pair, meaning the other member is to the left of that, meaning m - 1
. So,
return float(s[m - 1] + s[m]) / 2