# Advanced List Comprehension: Creating Averages

## 24 November 2018 - 1 answer

I have a list, each element in the list in a list containing 2 numbers separated by a comma.

I have to treat the first items in each list in relation with each other, same with the second ones.

Given a list, I have to replace the first number of each nested list with the average of the number, the first number in the list to its right and the first number in the list to its left. same to the second number. For the first nested list, I have to replace it the average or the number itself and its matching number in the list to its right. For the last, the same with the list to its left.

For example:

``````[[1, 1], [7, 7], [20, 20], [9, 9], [-12, -12]]
``````

would be:

``````[[(1+7)/2, (1+7)/2], [(7+1+20)/3, (7+1+20)/3], [(20+7+9)/3, (20+7+9)/3], [(9+20-12)/3, (9+20-12)/3], [(-12+9)/2, (-12+9)/2]]
``````

and thus:

``````[[4, 4], [9, 9], [12, 12], [5, 5], [-2, -2]]
``````

because we are returning ints.

I have a code but it only prints the average, which is kind of clunky. Please help me to point me to the right direction on how to calculate the elements, and create the new list.

Also, I would like to use only loops and basic list comprehensions, so I can understand the logic.

This is my code so far:

``````def lpf(lst):
for i in range(len(lst)):
for j in range(2):
if i == 0:
lst[i][j] = int((lst[i][j] + lst[i+1][j]) / 2)
elif 0 < i < (len(lst) - 1):
lst[i][j] = int((lst[i-1][j] + lst[i][j] + lst[i+1][j]) / 3)
elif i == len(lst) - 1:
lst[i][j] = int((lst[i-1][j] + lst[i][j]) / 2)
return lst
``````

And we have to assume the items in the list won't always be the same.

I seem to understand my code's problem - Once I change the first element, the next iteration happens over the new element and not the original. Yet I cant think about how to solve this.

You wanted list-comprehension, I give you list-comprehension:

``````[[sum(s[p] for s in l[i-1 if i > 0 else 0:i+2])//(2 if i in (0,len(l)-1) else 3) for p in range(2)] for i in range(len(l))]
``````

In all serious though, I would recommend breaking this down into a for-loop which contains the inner list-comprehension as it is just so unreadable.

Example of it working:

``````>>> l = [[1, 1], [7, 7], [20, 20], [9, 9], [-12, -12]]
>>> [[sum(s[p] for s in l[i-1 if i > 0 else 0:i+2])//(2 if i in (0,len(l)-1) else 3) for p in range(2)] for i in range(len(l))]
[[4, 4], [9, 9], [12, 12], [5, 5], [-2, -2]]
``````

Exploded form without list-comprehensions:

``````output = []
for i in range(len(l)):
if i == 0:
group = l[i:i+2]
averaged = [(group + group)//2,
(group + group)//2]
output.append(averaged)
elif i == len(l)-1:
group = l[i-1:i+1]
averaged = [(group + group)//2,
(group + group)//2]
output.append(averaged)
else:
group = l[i-1:i+2]
averaged = [(group + group + group)//3,
(group + group + group)//3]
output.append(averaged)
``````

which gives `output` as before:

``````[[4, 4], [9, 9], [12, 12], [5, 5], [-2, -2]]
``````