# Iteration over OffsetArray

**URL:** <https://discourse.julialang.org/t/iteration-over-offsetarray/81893>\
**Category:** General Usage\
**Tags:** indexing, arrays\
**Created:** [May 30, 2022, 2:01am UTC](https://discourse.julialang.org/t/iteration-over-offsetarray/81893 "2022-05-30T02:01:18Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![wsshin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wsshin/32/360_2.png) [@wsshin](https://discourse.julialang.org/u/wsshin)\
**Post date:** [May 30, 2022, 2:01am UTC](https://discourse.julialang.org/t/iteration-over-offsetarray/81893/1 "2022-05-30T02:01:18Z")

</div>

From [this comment](https://discourse.julialang.org/t/discussion-on-why-i-no-longer-recommend-julia-by-yuri-vishnevsky/81151/14), I learned that `for i = eachindex(v)` is preferred to `for i = 1:length(v)` when iterating over `v::AbstractVector`, because `AbstractVector` may not support 1-based indexing (e.g., `OffsecArrays.jl`).

`eachindex(v)` is acceptable when we want to iterate over the entire length of `v`. However, sometimes we want to iterate over a portion of `v`. For example, to calculate the gap between adjacent entries, we would want to do something like

```julia
for i = 1:length(v)-1
    println(v[i+1] - v[i])
end

```

In this case we cannot use `eachindex(v)`. Is there a syntax that we can use in such a case?

(Calculating the gap between adjacent entries is what `diff(v)` does, and `diff(v)` calls `Base.require_one_based_indexing(v)`, which suggests that there may not be a simple way of handling this issue.)

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [May 30, 2022, 2:18am UTC](https://discourse.julialang.org/t/iteration-over-offsetarray/81893/2 "2022-05-30T02:18:33Z")

</div>

> [@wsshin](#):
>
> `for i = 1:length(v)-1`

```julia
for i = firstindex(v):lastindex(v)-1

```

---

<div class="post-metadata">

**Author:** ![stillyslalom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stillyslalom/32/45687_2.png) [@stillyslalom](https://discourse.julialang.org/u/stillyslalom)\
**Post date:** [May 30, 2022, 4:35am UTC](https://discourse.julialang.org/t/iteration-over-offsetarray/81893/3 "2022-05-30T04:35:21Z")

</div>

Or

```julia
for i in eachindex(v)[begin:end-1]

```

which produces the same result - it’s mostly a matter of style/taste.

---

<div class="post-metadata">

**Author:** ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)\
**Post date:** [May 30, 2022, 4:41am UTC](https://discourse.julialang.org/t/iteration-over-offsetarray/81893/4 "2022-05-30T04:41:18Z")

</div>

And would this be a good replacement:

```julia
    # only for one based arrays
    x=vec[1]
    y=vec[2]
    # generic
    x=vec[firstindex(vec)]]
    y=vec[firstindex(vec)+1]

```

?

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [May 30, 2022, 4:54am UTC](https://discourse.julialang.org/t/iteration-over-offsetarray/81893/5 "2022-05-30T04:54:01Z")

</div>

~~this allocates a concrete array, `O(N)` in memory, would not recommend~~

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [May 30, 2022, 4:54am UTC](https://discourse.julialang.org/t/iteration-over-offsetarray/81893/6 "2022-05-30T04:54:29Z")

</div>

> [@ufechner7](#):
>
> ```julia
> x=vec[firstindex(vec)]]
> y=vec[firstindex(vec)+1]
> 
> ```

```julia
x = vec[begin]
y = vec[begin + 1]

```

it’s exactly how the `begin/end` syntax sugar works under the hood:

```julia
julia> Meta.@lower vec[begin + 1]
:($(Expr(:thunk, CodeInfo(
    @ none within `top-level scope`
1 ─ %1 = Base.firstindex(vec)
│ %2 = %1 + 1
│ %3 = Base.getindex(vec, %2)
└── return %3
))))

```

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [May 30, 2022, 5:05am UTC](https://discourse.julialang.org/t/iteration-over-offsetarray/81893/7 "2022-05-30T05:05:47Z")

</div>

> [@jling](#):
>
> this allocates a concrete array, `O(N)` in memory, would not recommend

I don’t believe that’s true.

```julia
julia> let v = OffsetArray([1,2,3,4,5], -2:2)
           eachindex(v)[begin:end-1]
       end
-2:1                                                                 
                                                                     
julia> typeof(ans)
UnitRange{Int64}
```

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [May 30, 2022, 5:07am UTC](https://discourse.julialang.org/t/iteration-over-offsetarray/81893/8 "2022-05-30T05:07:01Z")

</div>

oops, Julia is smarter than I thought, my bad

---

<div class="post-metadata">

**Author:** ![gustaphe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gustaphe/32/18174_2.png) [@gustaphe](https://discourse.julialang.org/u/gustaphe)\
**Post date:** [May 30, 2022, 5:25am UTC](https://discourse.julialang.org/t/iteration-over-offsetarray/81893/9 "2022-05-30T05:25:30Z")

</div>

> [@jling](#):
>
> > [@wsshin](#):
> >
> > `for i = 1:length(v)-1`
> 
> ```julia
> for i = firstindex(v):lastindex(v)-1
> 
> ```

This assumes a step length of 1. For complete generality you need to index into `eachindex(v)`.

---

<div class="post-metadata">

**Author:** ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)\
**Post date:** [May 30, 2022, 5:28am UTC](https://discourse.julialang.org/t/iteration-over-offsetarray/81893/10 "2022-05-30T05:28:40Z")

</div>

I would create `SubArray`s via `@view` or `@views`:

```julia
using OffsetArrays

v = OffsetArray([1,3,2,4,8,90], -5)
v_1, v_2 = @views v[begin:end-1], v[begin+1:end];
println.(v_2 .- v_1)

```

If you really wanted to use a for loop

```julia
for i in eachindex(v_1, v_2)
   println(v_2[i] - v_1[i])
end

```

---

<div class="post-metadata">

**Author:** ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)\
**Post date:** [May 30, 2022, 5:33am UTC](https://discourse.julialang.org/t/iteration-over-offsetarray/81893/11 "2022-05-30T05:33:53Z")

</div>

> [@gustaphe](#):
>
> This assumes a step length of 1. For complete generality you need to index into `eachindex(v)` .

Technically, the result of `axes(A)` where `typeof(A) <: AbstractArray` must be a `tuple of AbstractUnitRange{<:Integer}` according to the `AbstractArray` interface: [Interfaces · The Julia Language](https://docs.julialang.org/en/v1/manual/interfaces/#man-interface-array). The step should be `1`.

The problem is that we do not have a good way of enforcing this.

---

<div class="post-metadata">

**Author:** ![gustaphe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gustaphe/32/18174_2.png) [@gustaphe](https://discourse.julialang.org/u/gustaphe)\
**Post date:** [May 30, 2022, 5:51am UTC](https://discourse.julialang.org/t/iteration-over-offsetarray/81893/13 "2022-05-30T05:51:15Z")

</div>

TIL. I guess StarWarsArrays should not subtype AbstractArray then.

---

<div class="post-metadata">

**Author:** ![jishnub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jishnub/32/33620_2.png) [@jishnub](https://discourse.julialang.org/u/jishnub)\
**Post date:** [May 30, 2022, 7:40am UTC](https://discourse.julialang.org/t/iteration-over-offsetarray/81893/14 "2022-05-30T07:40:02Z")

</div>

Often, the simplest solution might be to use `OffsetArrays.no_offset_view`, which will return a 1-based view that will (for mutable arrays) share memory with the parent array. So

```julia
v1 = OffsetArrays.no_offset_view(v)
for i = 1:length(v1)-1 # works now
    println(v1[i+1] - v1[i])
end

```

This might lead to code that’s simpler to understand.

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [May 30, 2022, 9:22am UTC](https://discourse.julialang.org/t/iteration-over-offsetarray/81893/15 "2022-05-30T09:22:05Z")

</div>

> [@jling](#):
>
> oops, Julia is smarter than I thought, my bad

Indexing into a range with another range should produce a range. It’s not too hard to do.

---

<div class="post-metadata">

**Author:** ![cjdoris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cjdoris/32/213133_2.png) [@cjdoris](https://discourse.julialang.org/u/cjdoris)\
**Post date:** [May 30, 2022, 10:57am UTC](https://discourse.julialang.org/t/iteration-over-offsetarray/81893/16 "2022-05-30T10:57:09Z")

</div>

I believe the most idiomatic way is

```julia
for i = axes(v, 1)[begin:end-1]
    println(v[i+1] - v[i])
end

```

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [May 30, 2022, 11:19am UTC](https://discourse.julialang.org/t/iteration-over-offsetarray/81893/17 "2022-05-30T11:19:16Z")

</div>

> [@cjdoris](#):
>
> `axes(v, 1)[1:end-1]`

No, that doesn’t work. It must be `axes(v, 1)[begin:end-1]`:

```julia
julia> v = OffsetArray(rand(5), -1:3);

julia> eachindex(v)[1:end-1]
1:2

julia> eachindex(v)[begin:end-1]
-1:2

```

---

<div class="post-metadata">

**Author:** ![cjdoris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cjdoris/32/213133_2.png) [@cjdoris](https://discourse.julialang.org/u/cjdoris)\
**Post date:** [May 30, 2022, 11:33am UTC](https://discourse.julialang.org/t/iteration-over-offsetarray/81893/18 "2022-05-30T11:33:33Z")

</div>

Oops, yes, typo. Edited, thanks.
