Why is my median incorrect?

And further to that, consider the state of the list that is passed into the function. Do we wish to preserve its order? If so, the list.sort() method is not the tool to reach for as it will alter the order of the original list. Our functions should only mutate global objects when that is our strictest of intention, else leave things as they are.

2 Likes

I have checked and realized I should be using ‘sorted()’ instead. I also read that ‘.sort()’ gives ‘None’ in the console, which is what happened for me.

Do I need to know or care about why this is?

Other than that, thanks!

i would care, sort() orders the list in memory and return None

where as sorted returns a new list.

Like mtf says, if we use .sort(), we modify the original list, is this desirable?

1 Like

Hi,

Thanks for explaining the difference between the two. I have another question - what would be wrong in modifying the original list? below is my code that worked, and following that is code using the ‘.sort()’ function (that didn’t work).

def median(x):
  chrono = sorted(x)
  mid_pt = len(chrono)//2
  if len(x) % 2 == 0:
    even_median = (chrono[mid_pt] + chrono[mid_pt - 1]) / 2.0
    return even_median
  
  elif len(x) == 1:
    return chrono[0]

  else:
    odd_median = chrono[mid_pt]
    return odd_median
  
    

print median([10, 2, 11, 16, 8, 9])

Second set of code:


def median(x):
  chrono = x.sort()
  mid_pt = len(chrono)//2
  if len(x) % 2 == 0:
    even_median = (chrono[mid_pt] + chrono[mid_pt - 1]) / 2.0
    return even_median
  
  elif len(x) == 1:
    return chrono[0]

  else:
    odd_median = chrono[mid_pt]
    return odd_median
  
    

print median([10, 2, 11, 16, 8, 9])

Also,

I’m struggling to understand why the ‘.sort()’ function returns ‘None’ - surely it should just return the sorted (new) version of the list? In addition, when we would ever need it?

sort is an insitu method that does not create a copy. It sorts the actual list. To assign it, use sorted.

chrono = sorted(x)

This will create a copy of the list, then sort it, then assign it.

Further to this, using sorted does not affect the original global object’s order. Something we need to keep in mind. The order of the global object may be important as it could be the sequence of events, and therefore a record of occurrence.

How come this prints False? I wrote down ‘print median(1)’ because it said that False would appear when it was printed.

def median(last):
  result = 0
  if len(lst) == 0:
    return result
  elif len(lst) == 1:
    return result == lst
  elif len(lst) == 2:
    return result == (lst[0] + lst[1]) / 2
  lst = sorted(lst)
  if len(lst) % 2 != 0:
    return result == lst[((len(lst) - 1) / 2) + 1]
  else:
    return result == (lst[len(lst) / 2] + lst[(len(lst) / 2) + 1]) / 2
  
print median([1])

this is the bit of code that should be executed:

elif len(lst) == 1:
    return result == lst

we could use a print statement to see this is actually happening, and then also use this to inspect the values:

elif len(lst) == 1:
    print result, lst
    return result == lst

Oh okay, thanks for the help

Hey there! Could you please tell my why my inelegant code throws error here while giving the right result in PyCharm?

def median(list):
    list = sorted(list)
    if len(list) % 2 != 0 :
        return float(list[int(((len(list)+1) / 2) - 1)])
    else:
        return float((list[int(((len(list))/2) -1)] + list[int(((len(list))/2))] ) / 2)

different python versions very likely. The division behavior was among the things change in the python3 update

1 Like

@stetim94 is exactly right.
I ran your code on PythonTutor.com:

def median(list):
    list = sorted(list)
    if len(list) % 2 != 0 :
        return float(list[int(((len(list)+1) / 2) - 1)])
    else:
        return float((list[int(((len(list))/2) -1)] + list[int(((len(list))/2))] ) / 2)
        
print(median([7, 9, 1, 3, 4, 5])) #Python 2.7 prints 4.0 Python 3.6 prints 4.5   

Different outputs in Python 2 and Python 3. Since the exercise is in Python 2, you’ll have to make an adjustment.

What would you divine to make it less inelegant? Reduce repetition? Cache the math? Anything else?

I wanna share my code to see that it’s the best way to achieve this goal, if not it would be a pleasure to get corrected. Hope this is helpful to understand the Excercise.

Explain is based on the print statements at the end of the code :slight_smile:

def median(numbers):
  #sorted numbers
  sortnum=sorted(numbers)  
  #length of the list
  #if is odd our length is 5
  #if is even our length is 4
  lenum=len(numbers)  
  #then we need the middle of that list 
  #if its odd our mid is 2
  #if its even our mid is 2
  mid=lenum/2
  #here we be our median
  final=0 

# code to se if is even
  if lenum%2==0:
    #create middle to sum the middle values
    #so here our fist number is the index 2 that is 7
    middle=sortnum[mid]
    #then we add that number to the number with the index-1 = 2-1 = 1
    #in this case our index 1 is 6 and our var middle is 13
    middle+=sortnum[(mid-1)]
    #finaly we made the average of that sum result(dont forget to divide
    #by float(2.0)) So final will be 13/2.0=6.5
    final=middle/2.0
  else:
    #if is odd our median will be the index 2 of our sorted list
    #in this case is 6
    final=sortnum[mid]
  #Return our result
  return final
#odd
print median([7, 12, 3, 1, 6])
#even
print median([7, 12, 3, 6]) 
1 Like

It is easier to write critical analysis when we have the raw text code from the editor. Given as above we would need to re-type the whole thing to be able to test it. Please post the code in your reply.

That said, object.sort() is an in-place process (acts directly upon object) with no return value. But no matter, your program never uses sortNum.

Ideally, we should not do in-place sort on lists that are given as arguments. That will change the list at its source. Better to do as you have, but using the copy sort function,

sortedNums = sorted(numbers)

then actually use that copy. numbers will remain unchanged in caller scope.

1 Like

Oh yeah, of course, let me attach it

1 Like
```

paste code in here

```

The backtick is typically at the left end of the number key row. Give them their own line.

1 Like

Didn’t noticed that I didn’t use the sortnum variable, now its corrected!
Thank you so much mtf for feedback!

You’re welcome!.

Here is a spoiler of my preferred way to compute a median…

median.py
def median(sample):
    s = sorted(sample)
    n = len(s)
    m = n // 2
    return s[m] if n % 2 else (s[m - 1] + s[m]) / 2

That is a Python 3 supported function. Python 2 might have to be handled in a slightly different way (such as your coercive float, ... / 2.0).

It is important that m is an integer since it is an index. Be sure your code coerces or casts an integer for that value.


It should be noted that the only required verbosity is in the code and long names, all the rest are symbols (as such). We know it is median, and we know our list is a sample. sorted and len are self-documenting. Any further verbosity is unnecessary for the reader.

1 Like

#Below is my simple code that works. I hope it helps all newbies just like me :slight_smile:

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

x = [1,3,6,8,13,22,35,7,45,5,2,28,39,4]
print median(x)