Reputation: 1373
I am trying to create a function that, for each member of a list, returns the value of that member and the number of values either side of it. The only trick is that it has to "wrap around" when it is at the start or end of the list
For example:
a = [0,1,2,3,4,5,6,7,8,9]
myfunc(a,2) # 2 indicates 2 either side
[8,9,0,1,2]
[9,0,1,2,3]
[0,1,2,3,4]
...
...
[6,7,8,9,0]
[7,8,9,0,1]
I can work out how to do it from index 2 until 7:
def myfunc(vals, rnge):
for i in range(0+rnge, len(vals)-rnge):
print vals[i-rnge:i+rnge+1]
But I can't work out how to handle when it needs to wrap around.
Upvotes: 2
Views: 989
Reputation: 126
Generate your lists using the numpy element-wise modulo of an (unshifted) array.
You want 5 elements that wrap around 10, so use modulo 10. For example if the list starts with 8:
np.mod(np.arange(8,8+5,1),10) returns [8, 9, 0, 1, 2]
To get all 10 possible lists, evaluate list(np.mod(np.arange(s,s+5,1),10))
for each start s=1,2,..,10
Or, in a single list comprehension without resorting to numpy,
[[t%10 for t in range(s,s+5)] for s in range(10)]
returns
[[0, 1, 2, 3, 4],
[1, 2, 3, 4, 5],
[2, 3, 4, 5, 6],
[3, 4, 5, 6, 7],
[4, 5, 6, 7, 8],
[5, 6, 7, 8, 9],
[6, 7, 8, 9, 0],
[7, 8, 9, 0, 1],
[8, 9, 0, 1, 2],
[9, 0, 1, 2, 3]]
Upvotes: 2
Reputation: 46779
Here is an alternative approach you might also find useful:
def myfunc(alist, offset):
adeque = collections.deque(a)
adeque.rotate(offset)
for i in xrange(len(alist)):
print list(itertools.islice(adeque, 0, 2*offset+1))
adeque.rotate(-1)
a = [0,1,2,3,4,5,6,7,8,9]
myfunc(a,2) # 2 indicates 2 either side
It makes use of the deque
collections object which has an efficient rotate
function.
Upvotes: 1
Reputation: 631
How about:
def myfunc(vals, rnge):
valsX3 = vals*3;
for i in range(len(vals)):
print valsX3[i:i+2*rnge+1]
You could use something like this to avoid the duplication of arrays: wrapping around slices in Python / numpy
Not sure how it does it internally though.
Upvotes: 1
Reputation: 46911
you could try this (extend vals
in both directions first). there may be something in collections
that allows for this to be done more efficiently:
def myfunc(vals, rnge):
vals_ext = vals[-rnge:] + vals + vals[:rnge]
for i in range(len(vals)):
print( vals_ext[i:i+2*rnge+1] )
output:
[8, 9, 0, 1, 2]
[9, 0, 1, 2, 3]
[0, 1, 2, 3, 4]
[1, 2, 3, 4, 5]
[2, 3, 4, 5, 6]
[3, 4, 5, 6, 7]
[4, 5, 6, 7, 8]
[5, 6, 7, 8, 9]
[6, 7, 8, 9, 0]
[7, 8, 9, 0, 1]
Upvotes: 2
Reputation: 7629
Here is the solution :
def defunc(vals, start, rnge):
n = len(vals)
new = []
for i in xrange((start - rnge), (start + rnge)+ 1):
new.append(vals[i%n])
return new
def myfunc(vals, rnge):
n = len(vals)
for i in range(n):
print defunc(vals,i,rnge)
I am not slicing the list to make the logic clearer.
I hope this works
Upvotes: -1