When I first discovered this I thought, cool! After a good long while something I'd read began to sink in that made it not so cool, anymore. Fudging code is what it is, when you consider that 2 is a counting number, 2.0 is not. 2 is 1/2 of 4. 2.0 is not; it's 1/2 of 4.0.
When a counting number is in the denominator, and we expect our quotient to be a float, then set the numerator to float. Avoid fudging the denominator. It's a mistake to think this is good coding. It is not. Implicit typing of values is a slippery slope that can be avoided by making everything perfectly clear. Be explicit.
return float(n[p] + n[y]) / 2
as an example.
Okay, now on to the real question, and the real answers. If we do not wish to mutate the list given to the function we can clone it with a shallow slice:
y = x[:]
Anything we do to y won't affect x which is in global scope and may have a particular order that is meant to be preserved. x is now out of the picture.
Next we sort, and let's cache the length, and the floor value of half this,
u = len(y)
n = u / 2
I didn't have to specify floor() since u is an integer and integer quotients are always floor values. Float quotients are floats, even when we use floor division...
a = 3.5
b = a // 2
print b # 1.0
Given the three data objects we have above, y, u, and n we have enough to work with.
if u % 2 != 0:
return float(y[n-1] + y[n]) / 2
We've essentially done everything you did, with one exception, which I've written twice in this post. That one change and your code should work, too. No need to replace it.