Why do I have to include the `/2` in the `int()`?

Middle Item

I am a little embarrassed to say this but I have come back to this challenge every day for a week and still can’t remember the solution the next day. I think my problem is that I don’t understand why in:

sum = lst[int(len(lst)/2)] + lst[int(len(lst)/2) -1]

this line of code, the int() is not only for the len(lst). Why do I also have to include the “/2” in the int… and even further, why NOT include the “-1”? Maybe if I understood the reason, I would be able to rationalize it and remember.

In this mockup, think of each [_] as an element in a list.

[
  [_],
  [_],
  [_],
  [_],    #  m - 1
  [_],    #  m
  [_],
  [_],
  [_]
]

The length is 8. To find the approximate middle of the list we divide by 2, which gives 4. We know that lists are zero-indexed so this means the fifth element is part of the middle pair (even length lists need two indexes). So if m = len(lst) // 2, then the middle pair is at lst[m - 1] and lst[m].

Note that when the list is even length, the division results in an integer (or integer equivalent), but when the length is odd, the division will result in a float. That is why we need the int() value, since indexes must be integer. Above I use the integer (floor) division operator rather than the int() constructor.

9 / 2     =>  4.5
9 // 2    =>  4

In Python 3, all division returns a float quotient, and since 4.0 is a float, it cannot be used as an index.

8 / 2     =>  4.0
8 // 2    =>  4
8 Likes

I think it was the last part, the fact that all division leads to a float, that got me. I now remember them teaching that in the very beginning! I need to make sure to add it to my notes. Thank you so much for the thorough explanation!

3 Likes

Hi,

I understand the idea. I tried to do this only by floor division. In the end I get also minus -7 . But with this code:

#Write your function here
def middle_element(lst):
  if len(lst) % 2 == 1:
    index = (len(lst) - 1) / 2
    mid_element = lst[index]
    return mid_element
  
  else:
    index1 = (len(lst) // 2) - 1
    # (6.0 / 2) - 1 = 2
    index2 = (len(lst) // 2)
    # (6.0 / 2) = 3
    average = (lst[index1] + lst[index2]) // 2
    return average

#Uncomment the line below when your function is done
print(middle_element([5, 2, -10, -4, 4, 5])) # index 2 and 3

the console shows “-7” but I get an error message “list indices must be integers or slices, not float”

is my assumption right?

 index1 = (len(lst) // 2) - 1
    # (6.0 / 2) - 1 = 2
    index2 = (len(lst) // 2)
    # (6.0 / 2) = 3

I am sorry I was looking at these lines yesterday and today again. Now I see the mistake:

def middle_element(lst):
  if len(lst) % 2 == 1:
    **index = (len(lst) - 1) / 2** # should be //
    mid_element = lst[index]
    return mid_element

Not sure, why, -1?

lst = [2, 4, 6, 8, 10, 12, 14]
n = len(lst)            # 7    note that n is an integer
m = n // 2              # 3    index is an integer
v = lst[m]              # 8    value at index


lst = [2, 4, 6, 8, 10, 12, 14, 16]
n = len(lst)            # 8    note that n is an integer
m = n // 2              # 4    index is an integer
v = lst[m]              # 10   value at index
u = lst[m-1]            # 8    value at index - 1
x = float(u + v) / 2    # 9.0  average of u and v
1 Like

In that case -1 is necessary if if I just use normal “/” division. in case of floor division it’s not necessary.

It’s arbitrary, and basically fudging the outcome. We know that for an even list, the length divided by 2 gives the upper index of the middle pair of elements. The lower index is 1 less.

For an odd length, the middle element is the integer quotient of dividing by 2. We don’t need to subtract 1. Bear in mind zero-indexing.

9 / 2 => 4.5

We want an integer, so if not floor dividing, then one supposes we can subtract 1 then divide; that will work. We could also cast the quotient to integer,

int(9 / 2)

Floor division is the simplest, however.

1 Like

once I had the answer to this problem:

#Write your function here
def middle_element(lst):
if len(lst) % 2 == 0:
sum = lst[int(len(lst)/2)] + lst[int(len(lst)/2) - 1]
return sum / 2
else:
return lst[int(len(lst)/2)]

#Uncomment the line below when your function is done
print(middle_element([5, 2, -10, -4, 4, 5]))

Answer is -7

I could go back and follow the code that got there. I found “middle_element” confusing.
Why not just def it as the median? It would have made it easier to understand what to do and how to get there.

Because it is not the median (a statistical value) we are after, only the middle one or two elements of an unsorted list. It could be preparatory for a median problem, but is not one.