2

Let's say I have

arr = np.arange(6)
arr
array([0, 1, 2, 3, 4, 5])

and I decide that I want to treat an array "like a circle": When I run out of material at the end, I want to start at index 0 again. That is, I want a convenient way of selecting x elements, starting at index i.

Now, if x == 6, I can simply do

i = 3
np.hstack((arr[i:], arr[:i]))
Out[9]: array([3, 4, 5, 0, 1, 2])

But is there a convenient way of generally doing this, even if x > 6, without having to manually breaking the array apart and thinking through the logic?

For example:

print(roll_array_arround(arr)[2:17])

should return.

array([2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0])
1
  • You could write a function roll_array_around(arr, startIndex, endIndex) that returns an array. If you had a function roll_array_around(arr) - i.e., it just took arr as a parameter - then you would theoretically need to return an infinite array. Commented Apr 12, 2018 at 8:09

4 Answers 4

2

See mode='wrap' in ndarray.take:

https://docs.scipy.org/doc/numpy/reference/generated/numpy.take.html

Taking your hypothetical function:

print(roll_array_arround(arr)[2:17])

If it is implied that it is a true slice of the original array that you are after, that is not going to happen; a wrapped-around array cannot be expressed as a strided view of the original; so if you seek a function that maps an ndarray to an ndarray, this will necessarily involve a copy of your data.

That is, efficiency-wise, you shouldnt expect to find solution that significantly differs in performance from the expression below.

print(arr.take(np.arange(2,17), mode='wrap'))
Sign up to request clarification or add additional context in comments.

Comments

2

Modulus operation seems like the best fit here -

def rolling_array(n, x, i):
    # n is rolling period
    # x is length of array
    # i is starting number
    return np.mod(np.arange(i,i+x),n)

Sample runs -

In [61]: rolling_array(n=6, x=6, i=3)
Out[61]: array([3, 4, 5, 0, 1, 2])

In [62]: rolling_array(n=6, x=17, i=2)
Out[62]: array([2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0])

Comments

1

A solution you can look into would probably be :

from itertools import cycle
list_to_rotate = np.array([1,2,3,4,5])
rotatable_list = cycle(list_to_rotate)

Comments

-1

You need to roll your array.

>>> x = np.arange(10)
>>> np.roll(x, 2)
array([8, 9, 0, 1, 2, 3, 4, 5, 6, 7])

See numpy documentation for more details.

1 Comment

I don't think that is what OP means. OP is trying to use an array as an infinite circular queue. Look at OP's example, len(arr) is just 6, but OP wants to get arr[2:17] which definitely exceeds even double length.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.