incapable moron - 4 months ago 11

Python Question

I have a function that takes a list and removes (one instance of) the smallest and largest elements, then takes the average of the remaining elements.

Running it doesnt bring up any errors, although on checking the results I realised they were incorrect.

Here's the program:

`def centered_average(x):`

x.sort()

y = 0

for i in x:

if x.index(i) == 0 or x.index(i) == (len(x)-1):

print(i, "is being removed")

x.remove(i)

i +=1

else:

y += i

print(i, "is being added")

return (y / len(x))

def average(x):

return sum(x)/len(x)

(the print functions were put in for checking)

On putting through a list of

`x = [1,2,3,4,5]`

the result was:

`1 is being removed`

3 is being added

4 is being added

5 is being removed

2.3333333333333335

therefore, we can assume x[1] is not being used in the function, and I would like to know why.

Thanks in advance for any help.

Answer

You need to take special care when removing elements of a list that you are already iterating over in Python, as you are doing in your function. Python is looking at the indices of the list and using those, but when you remove the first element and the list is updated in place, the previous second element (`x[1]`

) is now the first (`x[0]`

) and will thus be skipped.

There is an easier way to do this, though, that doesn't require such a loop and the extra conditionals, if all you want to do is take the average of the elements that aren't the first or last:

```
def centered_average(x):
x.sort()
if len(x) <= 2:
print "Cannot run with 2 or fewer elements..."
return 0
else:
return sum(x[1:-1])/(len(x)-2.00)
```

There are other ways to do this, but this one should be fast enough and allow for any case you provide as long as **x** is a list. Hope this helps.