Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing an array some elements at a time and wrapping round to the beginning

I have a simple question that should have a simple answer but I can't think of it yet. I want to process an array, a certain number of elements at a time, and wrapping round to the beginning.

Here's a diagram showing when n is 10 and three elements are wanted each time:

iterations 3 at a time

My attempts to write a simple iteration so far have failed: using % n gives me zeros, which don't work with Julia's one-indexing... :)

like image 906
daycaster Avatar asked Sep 29 '16 18:09

daycaster


People also ask

Which array method would you use to add an element to the beginning of an array?

The unshift() method adds one or more elements to the beginning of an array and returns the new length of the array.

How do you push to the beginning of an array?

The unshift() method adds new elements to the beginning of an array.

How do you wrap an array in Java?

An int array can be wrapped into a buffer using the method wrap() in the class java. nio. IntBuffer. This method requires a single parameter i.e. the array to be wrapped into a buffer and it returns the new buffer created.

Do arrays wrap around?

Wrap-around array is implemented in the form of a class template (Warr class) and thus allows elements of any type. The idea of such an array is to have it in the form of a loop. If S – size of the wa-array, then indices 0,1,2…,S-1 point to all elements of that array.


1 Answers

The mod1 function is provided to allow the behaviour you desire:

julia> mod1(1, 5)
1

julia> mod1(3, 5)
3

julia> mod1(5, 5)
5

julia> mod1(6, 5)
1

It's pretty straightforward to make a mod-indexed function:

modindex(A, i) = A[mod1(i, length(A))]

Or even your own mod-indexed array type:

julia> immutable CircArray{T} <: AbstractArray{T,1}
           xs::Vector{T}
       end

julia> Base.size(x::CircArray) = (length(x.xs),)

julia> Base.getindex(x::CircArray, i) = x.xs[mod1(i, length(x.xs))]

julia> A = CircArray([1:2:10;])
CircArray{Array{Int64,1}}([1,3,5,7,9])

julia> A[0]
9

julia> A[5]
9

julia> A[7]
3

It is not too difficult to implement slicing on top of this. As DNF mentioned in a comment, a clean and concise solution is

modindex(A, i) = A[mod1.(i, end)]

or the equivalent for getindex, which handles both scalar indexing and slicing.


Edit: Since your question mentioned iteration, I figure I'd provide a more general solution that also works on non-arrays for iteration purposes, using only the functional iterables in Base:

julia> threes(A) = let cy = cycle(A)
           take(zip(cy, drop(cy, 1), drop(cy, 2)), length(A))
       end
threes (generic function with 1 method)

julia> for (a, b, c) in threes([1, 2, 3, 4, 5])
           println(a, b, c)
       end
123
234
345
451
512
like image 198
Fengyang Wang Avatar answered Oct 16 '22 20:10

Fengyang Wang