Create new list where each new element is the average of the old element and the 2n sourrunding elements

Hi there!

I am very new to coding and I could really use some help with an assignment.

The goal is to write a function that accepts a list x and a integer n (as argument) and returns a new list r, where each elements are the average of the original and the surrounding 2n elements.
In addition: The interval 2n should never count beyond the list.

For example:
If the original list (argument x) is [1, 2, 6, 4, 5, 0, 1, 2] and n=1, the new list r should be
[1.5, 3.0, 4.0, 5.0, 3.0, 2.0, 1.0, 1.5]. As the iteration hits the first element in r, only(!) the average of that and the second should be calculated ((1+2)/2 = 1.5).

The code i’ve written so far is:

def smooth_b(x, n):

for i in range(len(x)):

which only works for the elements were the interval stays between the borders in the original list x. The result I get so far is:
[0.0, 3.0, 4.0, 5.0, 3.0, 2.0, 1.0, 1.0].

This is, as I said, an assignment for my course, so I am not asking for it to be solved completely, but I am utterly stuck and could really use some guidance.
Thank you so much in advance!

Best regards,

There’s two problems you need to solve:

  1. the list that’s summed is not always 2*n+1 elements long. The easiest way solve that is use the len function
  2. “i-n” can be smaller than 0, which doesn’t do what you want here. The easiest way to solve that is to use the max function to ensure that the value is at least 0.

Thank you for your reply!

I understand what you mean and I´ve been trying implementing the max function, but honestly I don’t really know what I’m doing.
I’ve tried to assign (i-n) to a variable and then constrict that variable between an interval, but that dosen’t work.

Could you tell me something about how I should implement the max function?

Best regards,

there’s a builtin max function that you can use, max(a, b) returns the larger of a and b.

Hi Elias,

You have a list like this:

L = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

and you need to take a sliding window of width 2n from that list:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

In my example, instead of using some set of arbitrary or random values,
I have used 0, 1, 2, … inside the list. Those numbers match the index
of each element. That makes it easy for us to see the indices.

We can see:

  • Every window is the same width.

  • Each step, the window advances by exactly 1.

  • The process stops when the end of the window reaches the end of the
    list, in this case index 9.

  • Which corresponds to the start of the window reaching index 4.

If your data list is L, then you can grab a window using a slice:


where the start index is included in the slice and end is one past
than final index included. So if the width is 6, the first window would


and the following windows will be:

L[1:7], L[2:8], L[3:9], L[4:10]

So let’s run some test code to make sure we have the logic right. Using
a width of 6, we have:

L = list(range(10))
for start in range(5):  # Remember, 5 is *one past* the last value

Run that code and confirm that it gives you the expected sublists.

Some hints to continue from that point:

  • Instead of hard-coding start + 6 in the slice, the width needs to be
    calculated as 2*n. That should be an easy change to make.

  • A little bit trickier: currently I set the end condition using a hard-
    coded 5 in the range(5). But the actual end condition depends on
    both the length of the list L and the width 2*n. Can you work out a
    formula for calculating the end condition instead of a hard-coded 5?

  • Instead of printing the slices L[start:start+6] we want to work out
    their average, also known as the “mean”. Do you know how to do that?
    (Hint: try looking at the “statistics” module.)

  • Those means should be accumulated into a new list.

  • Then we want to wrap all that code into a function.

  • And finally you should test the function to confirm it gives you
    the expected results.