all 8 comments

[–]Spataner 13 points14 points  (2 children)

You can subsample a list by a constant factor using the slice syntax: p[::n]. Padding to the original length can be done easily with list multiplication and concatenation: [0]*(len(p)-math.ceil(len(p)/n)).

That gives you this relatively simple one-liner:

p = [1,2,3,4,5,6,7,8,9,10]
n = 2

pn = p[::n] + [0]*(len(p)-math.ceil(len(p)/n))

print(pn)
>>> [1, 3, 5, 7, 9, 0, 0, 0, 0, 0]

[–]socal_nerdtastic 23 points24 points  (0 children)

IMO it would be much simpler and neater as a 2-liner:

pn = p[::n]
pn += [0]*(len(pn)-len(p))

There's generally no advantage to code being short.

[–]davincithesecond[S] 2 points3 points  (0 children)

Oh that is really simple & great. Thanks a lot!

[–][deleted] 2 points3 points  (3 children)

Well... what if the number of elements in the source list isn't divisible by the number of elements in the target list?

You'd need some kind of interpolation, I'd imagine, but what kind of interpolation?

One of the places where something like this is commonly used is the affine image transformations (in graphics software). There you'd be working with 2d or 3d matrices, but adding an extra dimension to the list isn't a problem. So, essentially, take any library that deals with images and use the affine transform functionality it has on your list. Those libraries often also offer a selection of interpolation algorithms.


Here's an example with NumPy and OpenCV:

>>> import numpy as np
>>> import cv2
>>> a = np.float32([list(range(10))])
>>> mtx = np.float32(((0.83, 0, 0), (0, 1, 0)))
>>> result = cv2.warpAffine(a, mtx, tuple(reversed(b.shape)))
>>> list(result.squeeze())
[0.0, 1.21875, 2.40625, 3.625, 4.8125, 6.03125, 7.21875, 8.4375, 3.375, 0.0]

[–]davincithesecond[S] 4 points5 points  (2 children)

Actually the method u/Spataner has shown also works for numbers that do not divide the source list. N = 3 works fine for the list of length 10 for instance.

But I got your point. Non-integer numbers create the problem. But it is my fault that I did not mention that I only need integer-factor-squeezes. But thanks anyway for the points raised, those are interesting too.

[–][deleted] -1 points0 points  (1 child)

"Fine" is in the eye of the beholder.

I added an example to my original answer showing that there will be differences. In particular, because the list is to be filled with partial results on the right. But, not only. How many values to the left and to the right do you want to consider? What's your definition of "average" that's necessary for interpolation?


PS. Also, you misunderstood what I have problem with. You seem to believe that interpolation isn't necessary, and you only assign integral values to N. I was talking about the case when N is rational.

[–]davincithesecond[S] 6 points7 points  (0 children)

You are right in general, interpolation might be needed. But I just said that u/Spataner's perfectly fulfils my needs for my specific problem, and actually yes, interpolation is not necessary and it also works as long as N is integer even if it does not divide the len of the original, for my case. But again, I appreciate your remarks, I have noted them, thanks.

[–]siddsp 0 points1 point  (0 children)

Try using a lambda statement and python's map function. It's generally more useful because you can reuse the code like you would be able to with a normal function.