Why are the preceding **lst** required?

Middle Item

I have 2 questions with this solution;

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

I get that these sections of code are indices for the two middle integers in the list. And that they are being added together so we can return the average in the next line. But why are the preceding lst required?

if len(lst) % 2 == 0:

Can anyone explain what the “%” function actually does? How it works etc

That is called a parity check, or a check for evenness. The modulo operator, % indicates remainder division. If a number divided by 2 has no remainder, then the number is even.

This relates to a statistics concept, median which is the middle of a sorted sample list. If the list is even-length, then we need to draw out the middle two indexes; if odd we use only the single middle index.

It’s not the integers that we are drawing out, but the indexes for those elements. Once we have the two middle indexes we can poll the values, add them and take their average as the median.

Note that in this exercise we are not sorting the list, only finding the physical middle of the list, not the median.

We can see in the earlier example that rather than repeat len(lst) / 2 or 1en(lst) we cache those values in n and m.

n = len(lst)    # n will be an integer
m = n // 2      # because we use integer (floor) division, m is an integer

Now with this information all we need to determine is the parity of the length so we know whether to return one term, or the average of two.

if n % 2:
    return lst(m)
else:
    return float(lst[m - 1] + lst[m]) / 2
9 Likes

ty very much. I couldn’t figure out how to get the function to determine if the list was odd or even the explanation of the mdoulo operator helps tremendously.

1 Like

Hello mtf :slight_smile:

I’ve read all 3 topics linked to this exercise, and researched more on floor division to try to fully understand the concept of your solution:

if n % 2:
    return lst(m)
else:
    return float(lst[m - 1] + lst[m]) / 2

It is very concise and it will help me greatly if you could clarify this section:

if n % 2:

This is an example I did for myself to understand better:

def middle_element(lst):
    a = len(lst)
    b = a // 2          
    if b % 2:
        return lst[b]
    return (lst[b] + lst[b-1]) / 2

I know for odd elements, b % 2 = 1 and for even elements, b % 2 = 0.

As the function just writes if b % 2: instead of if b % 2 == 1: or if b % 2 == 0, I want to confirm if this is left as such as default since the floor division (// 2) is already done, so the outcome of if b % 2: is limited to 2 absolute answers.

This will make sense for the subsequent return line on the same indent level as if b % 2.

In my example below, the answer printed -7.0, which is strange.

def middle_element(lst):
  a = len(lst)                                  #6 elements
  b = a // 2                                    #6//2 = 3
  if b % 2 == 0:                             #if 3 % 2 = 1 == 0:
    return lst[b]                              #return lst[3] = -4
  return (lst[b] + lst[b-1]) / 2       # return -4 + -10 / 2 = -7.0

print(middle_element([5, 2, -10, -4, 4, 5]))

I have been staring at these for hours, maybe I need to look at it again.

I hope you can shed some light on this, I appreciate your contributions!

In evaluating the predicate to if (as well as while), Python considers any of the following as False:

  • 0 (zero), False, None, any empty container (string, list, dictionary or tuple), or any expression that evaluates to one of the preceding

… and it considers any other object as True.

So the statement if x % 2: is read something like this:

“Evaluate the expression x % 2 to obtain a value. If that value is 0, return False, and do not enter the if block, but proceed rather to elif or else (if present); if that value is any other number, return True, and execute the if block.”

for n in [1,2,3,4]:
    if n % 2:
         # runs if n % 2 != 0
        print("{} % 2 is {}. The number {} is odd". format(n, n % 2, n))
    else:
        # runs if n % 2 == 0
        print("{} % 2 is {}. The number {} is even". format(n, n % 2, n)) 

# Output:
1 % 2 is 1. The number 1 is odd
2 % 2 is 0. The number 2 is even
3 % 2 is 1. The number 3 is odd
4 % 2 is 0. The number 4 is even

Hello Patrick,

This is truely helpful for me.

I have one example here, that I don’t quite get, I’ve tried running it on mu-editor too and it gives me -4, instead of -7.0 as the answer as well. I’m not sure where I missed out, could you shed some light?

lst = [5, 2, -10, -4, 4, 5]

def middle_element(lst):
  a = len(lst)                                     #6 elements
  b = a // 2                                       #6//2 = 3
  if b % 2:                                         #if 3 % 2 = 1 != 0:
     return lst[b]                               #return lst[3] = -4
  return (lst[b] + lst[b-1]) / 2          # return -4 + -10 / 2 = -7.0

print(middle_element([5, 2, -10, -4, 4, 5]))  #prints -4 as answer instead of -7.0

Thank you :slight_smile:

The problem is that you use b % 2 to tell you something, when it actually does not:

If list length is 6 (even), then b is 3 (odd), and b % 2 is True. If list length is 8 (also even), b is 4 and b % 2 is False.

Alright, I’m climbing out of the rabbit hole now!

So I’ll just stick to this at the moment:

def middle_element(lst):
  if len(lst) % 2 == 0:
    sum = lst[int(len(lst)/2)] + lst[int(len(lst)/2) - 1]
    return sum / 2
  return lst[int(len(lst)/2)]

Thank you Patrick! :slight_smile:

1 Like

Did you mean, lst[m]?

Will be truthy if the modulo is non-zero. if always evaluates the truth value and will only allow True to pass into the contained block.

As for the floor division, when two integers are divided, the floor will be an integer. When one or both are floats, the floor will be a float. In either case, the result will be the equivalent of an integer.

it’s important that we produce an integer since it will be used as an index. Floats cannot be indices.

Now let’s look at your code an determine what might be wrong about it.

b = a // 2

That should give us the middle index of an odd length list, or the higher of the two middle terms in an even length list.

if b % 2

It is not the index we wish to check for parity, but the full length…

if a % 2
1 Like

Hey mtf,

Thank you for your input! I think now I understand where I got mixed up in my code, because I was trying to combine some lines that I thought would lead me to get a result.

I fixed my code, looked through it. It’s giving the correct output and now I understand how. Thank you and Patrick again!

def middle_element(lst):
     a = len(lst)
     b = a // 2            #gets an integer via floor division
     if a % 2:              #runs if != 0, everything True
          return lst[b] 
     return (lst[b] + lst[b-1]) / 2   #runs for everything False

print(middle_element([5, 2, -10, 4, 6, 5, 8, 10]))
2 Likes