# \`eachindex(x)\` replacement for \`1:length(x)-1\` and similar

**URL:** <https://discourse.julialang.org/t/eachindex-x-replacement-for-1-length-x-1-and-similar/81481>\
**Category:** General Usage\
**Created:** [May 23, 2022, 2:49am UTC](https://discourse.julialang.org/t/eachindex-x-replacement-for-1-length-x-1-and-similar/81481 "2022-05-23T02:49:26Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![maxkapur](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maxkapur/32/21208_2.png) [@maxkapur](https://discourse.julialang.org/u/maxkapur)\
**Post date:** [May 23, 2022, 2:49am UTC](https://discourse.julialang.org/t/eachindex-x-replacement-for-1-length-x-1-and-similar/81481/1 "2022-05-23T02:49:26Z")

</div>

I have been following the [discussion](https://discourse.julialang.org/t/offsetarrays-inbounds-and-confusion/81295/49) lately about how functions that take an `AbstractArray` argument should avoid using the pattern `1:length(x)` as an iterator because it is incompatible with interfaces like OffsetArrays.jl.

`1:length(x)` can be easily replaced with `eachindex(x)`, but what about patterns like `1:length(x)-1`, `2:length(x)`, `1:2:length(x)` and so on that are needed occasionally?

Assuming 1D arrays, we have `eachindex(A)[begin:end-1]`. But this seems kind of clunky, or is it just me? It would be nice (from my very constrained viewpoint) if `eachindex` had optional arguments that let you “trim” the endpoints, something like `eachindex(A, begin, end-1)`.

- What’s the best generic replacement for `1:length(x)-1`?

---

<div class="post-metadata">

**Author:** ![KyleVaughn](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kylevaughn/32/36029_2.png) [@KyleVaughn](https://discourse.julialang.org/u/KyleVaughn)\
**Post date:** [May 23, 2022, 3:05am UTC](https://discourse.julialang.org/t/eachindex-x-replacement-for-1-length-x-1-and-similar/81481/2 "2022-05-23T03:05:38Z")

</div>

I think `Base.Iterators.take(eachindex(x), 1)` might work as a replacement for `1:length(x)-1` compatible with OffsetArrays.jl, but I havent tested it. There are some other handy functions in Base.Iterators you could check out.

---

<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 23, 2022, 3:23am UTC](https://discourse.julialang.org/t/eachindex-x-replacement-for-1-length-x-1-and-similar/81481/3 "2022-05-23T03:23:09Z")

</div>

I think it’s important to remember, you don’t need to adapt your own projects to the full `AbstractArray` specification, only if your package can reasonably be expected to be used with arbitrary array types.

Note that `x[(begin+1):(end -1)]` doesn’t solve the problem of strided arrays. There is `Iterators.take`. But `x[eachindex(x)[2:(end-1)]]` is probably as flexible as it gets.

---

<div class="post-metadata">

**Author:** ![maxkapur](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maxkapur/32/21208_2.png) [@maxkapur](https://discourse.julialang.org/u/maxkapur)\
**Post date:** [May 23, 2022, 3:45am UTC](https://discourse.julialang.org/t/eachindex-x-replacement-for-1-length-x-1-and-similar/81481/4 "2022-05-23T03:45:18Z")

</div>

> [@gustaphe](#):
>
> you don’t need to adapt your own projects to the full `AbstractArray` specification

Isn’t this precisely the unsettled issue in the debate, though? Whether supporting arrays with nonstandard indices is part of the “contract” you sign as a developer when you put AbstractArray in your function signature?

---

<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 23, 2022, 4:00am UTC](https://discourse.julialang.org/t/eachindex-x-replacement-for-1-length-x-1-and-similar/81481/5 "2022-05-23T04:00:05Z")

</div>

The way I see it, as long as you don’t use `@inbounds`, the amount of index errors you get is the measure of whether you need to fix your implementation. If you’re writing an array utility package it matters, but if your package is the final consumer of arrays I don’t really see the issue with letting some things fail.

---

<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 23, 2022, 4:03am UTC](https://discourse.julialang.org/t/eachindex-x-replacement-for-1-length-x-1-and-similar/81481/6 "2022-05-23T04:03:25Z")

</div>

> [@maxkapur](#):
>
> What’s the best generic replacement for `1:length(x)-1` ?

```julia
firstindex(x) : lastindex(x) - 1

```

don’t ask me what to do if indices are not contiguous…

---

<div class="post-metadata">

**Author:** ![maxkapur](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maxkapur/32/21208_2.png) [@maxkapur](https://discourse.julialang.org/u/maxkapur)\
**Post date:** [May 23, 2022, 4:16am UTC](https://discourse.julialang.org/t/eachindex-x-replacement-for-1-length-x-1-and-similar/81481/7 "2022-05-23T04:16:09Z")

</div>

```julia
firstindex(x):step(eachindex(x)):lastindex(x)-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 23, 2022, 4:57am UTC](https://discourse.julialang.org/t/eachindex-x-replacement-for-1-length-x-1-and-similar/81481/8 "2022-05-23T04:57:33Z")

</div>

idk, what if the valid indicies are:

```julia
1, 2, 4, 87

```

---

<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 23, 2022, 5:15am UTC](https://discourse.julialang.org/t/eachindex-x-replacement-for-1-length-x-1-and-similar/81481/9 "2022-05-23T05:15:41Z")

</div>

[`AbstractArray`s must have `AbstractUnitRange` axes](https://discourse.julialang.org/t/offsetarrays-inbounds-and-confusion/81295/50), so such a situation isn’t worth preparing for.

---

<div class="post-metadata">

**Author:** ![abraunst](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/abraunst/32/6880_2.png) [@abraunst](https://discourse.julialang.org/u/abraunst)\
**Post date:** [May 23, 2022, 7:59am UTC](https://discourse.julialang.org/t/eachindex-x-replacement-for-1-length-x-1-and-similar/81481/10 "2022-05-23T07:59:43Z")

</div>

> [@gustaphe](#):
>
> But `x[eachindex(x)[2:(end-1)]]` is probably as flexible as it gets.

As it was pointed out in slack, this does not cut it for `OffsetArray`s , as the indices themselves are again an `OffsetArray`

---

<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 23, 2022, 8:21am UTC](https://discourse.julialang.org/t/eachindex-x-replacement-for-1-length-x-1-and-similar/81481/11 "2022-05-23T08:21:09Z")

</div>

`x[eachindex(x)[begin+1:end-1]]` is exactly equivalent to `x[begin+1:end-1]`, isn’t it? `getindex` is going to use `eachindex` internally anyway.

```julia
julia> x = OffsetArray(rand(5), 3)
5-element OffsetArray(::Vector{Float64}, 4:8) with eltype Float64 with indices 4:8:
 0.8182202442166823
 0.8737712267996881
 0.9098827587057597
 0.7470582568095908
 0.05815041488262762

julia> x[begin+1:end-1]
3-element Vector{Float64}:
 0.8737712267996881
 0.9098827587057597
 0.7470582568095908

julia> x[eachindex(x)[begin+1:end-1]]
3-element Vector{Float64}:
 0.8737712267996881
 0.9098827587057597
 0.7470582568095908

```

---

<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 23, 2022, 8:36am UTC](https://discourse.julialang.org/t/eachindex-x-replacement-for-1-length-x-1-and-similar/81481/12 "2022-05-23T08:36:33Z")

</div>

> What’s the best generic replacement for `1:length(x)-1`

To me, `eachindex(x)[begin:end-1]` seems more readable than `eachindex(x, begin, end-1)`. In the first case, it’s obvious that we’re simply looking at a subsection of the indices, whereas in the second case I’ll need to look at the docstring of `eachindex` to understand what’s happening.

---

<div class="post-metadata">

**Author:** ![maxkapur](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maxkapur/32/21208_2.png) [@maxkapur](https://discourse.julialang.org/u/maxkapur)\
**Post date:** [May 23, 2022, 8:42am UTC](https://discourse.julialang.org/t/eachindex-x-replacement-for-1-length-x-1-and-similar/81481/13 "2022-05-23T08:42:24Z")

</div>

Right, but (the bit inside of the `x[]` brackets) `eachindex(x)[begin+1:end-1]` is _not_ equivalent to `begin+1:end-1`. I think this is just an imperfectly chosen example on the part of that user. This question concerns the case where you actually need the indices (e.g. to do some kind of Fourier-type transform or moving-average thing that depends on their values), and not just the “slice” of `x`.

> [@jishnub](#):
>
> it’s obvious that we’re simply looking at a subsection of the indices, whereas in the second case I’ll need to look at the docstring of `eachindex` to understand what’s happening.

Fair enough.

---

<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 23, 2022, 8:52am UTC](https://discourse.julialang.org/t/eachindex-x-replacement-for-1-length-x-1-and-similar/81481/14 "2022-05-23T08:52:49Z")

</div>

An alternative to `eachindex(x)[begin+1:end-1]` is `UnitRange(eachindex(x))[2:end-1]`, although I’m unsure if that’s any more readable.

```julia
julia> x = OffsetArray(rand(5), 3);

julia> eachindex(x)[begin+1:end-1]
5:7

julia> UnitRange(eachindex(x))[2:end-1]
5:7

julia> eachindex(x)[begin:end-1]
4:7

julia> UnitRange(eachindex(x))[1:end-1]
4:7

```

The `UnitRange` axis has the advantage that _its_ indices begin at `1`, so it might be easier to deal with.

---

<div class="post-metadata">

**Author:** ![maxkapur](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maxkapur/32/21208_2.png) [@maxkapur](https://discourse.julialang.org/u/maxkapur)\
**Post date:** [May 23, 2022, 9:04am UTC](https://discourse.julialang.org/t/eachindex-x-replacement-for-1-length-x-1-and-similar/81481/15 "2022-05-23T09:04:37Z")

</div>

> The way I see it, as long as you don’t use `@inbounds` , the amount of index errors you get is the measure of whether you need to fix your implementation.

But if `x` is a zero-based array, then `x[1:length(x)-1]` is in bounds! So with **or without** the `@inbounds` macro, a calculation based on this index will be silently incorrect rather than throwing an error.

---

<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 23, 2022, 9:38am UTC](https://discourse.julialang.org/t/eachindex-x-replacement-for-1-length-x-1-and-similar/81481/16 "2022-05-23T09:38:54Z")

</div>

I would highly recommend using `@view` to create a `SubArray`.

```julia
julia> A = collect(1:10)
10-element Vector{Int64}:
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10

julia> B = @view(A[begin:end-1])
9-element view(::Vector{Int64}, 1:9) with eltype Int64:
 1
 2
 3
 4
 5
 6
 7
 8
 9

julia> eachindex(B)
Base.OneTo(9)

julia> C = @view(A[begin:2:end])
5-element view(::Vector{Int64}, 1:2:9) with eltype Int64:
 1
 3
 5
 7
 9

julia> C[:] .= -1
5-element view(::Vector{Int64}, 1:2:9) with eltype Int64:
 -1
 -1
 -1
 -1
 -1

julia> A
10-element Vector{Int64}:
 -1
  2
 -1
  4
 -1
  6
 -1
  8
 -1
 10

julia> for i in eachindex(C)
           C[i] = -i
       end

julia> C
5-element view(::Vector{Int64}, 1:2:9) with eltype Int64:
 -1
 -2
 -3
 -4
 -5

julia> A
10-element Vector{Int64}:
 -1
  2
 -2
  4
 -3
  6
 -4
  8
 -5
 10

```

---

<div class="post-metadata">

**Author:** ![pablosanjose](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablosanjose/32/7006_2.png) [@pablosanjose](https://discourse.julialang.org/u/pablosanjose)\
**Post date:** [May 23, 2022, 11:11am UTC](https://discourse.julialang.org/t/eachindex-x-replacement-for-1-length-x-1-and-similar/81481/17 "2022-05-23T11:11:17Z")

</div>

Let me emphasise again what was mentioned by @gustaphe above: remember that all the issue with `AbstractArray` iteration applies to “generic” codebases, i.e. those for which you want the user to be able to plug any weird AbstractArray implementation and have it just work.

The fact that Julia is powerful enough to allow this doesn’t mean at all that every piece of code should take advantage of this power. The delicate issue of full genericness applies more to developers of foundational libraries that aim to be solid and flexible building blocks for more specific applications.  
Otherwise, you might want to restrict the type of array you accept, using e.g. `Base.require_one_based_indexing`, or even just enforce `Array` as an input, instead of `AbstractArray`.

[Then again, it’s a great exercise in abstraction (and ambition!) to go full generic if you can. You will learn a lot.]

---

<div class="post-metadata">

**Author:** ![e3c6](https://avatars.discourse-cdn.com/v4/letter/e/e79b87/32.png) [@e3c6](https://discourse.julialang.org/u/e3c6)\
**Post date:** [May 23, 2022, 11:25am UTC](https://discourse.julialang.org/t/eachindex-x-replacement-for-1-length-x-1-and-similar/81481/18 "2022-05-23T11:25:30Z")

</div>

> [@jling](#):
>
> don’t ask me what to do if indices are not contiguous…

Is there a subtype of AbstractArray that restrict to contiguous indices?

---

<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 23, 2022, 11:36am UTC](https://discourse.julialang.org/t/eachindex-x-replacement-for-1-length-x-1-and-similar/81481/19 "2022-05-23T11:36:47Z")

</div>

Yes, all of them, apparently: [`eachindex(x)` replacement for `1:length(x)-1` and similar - #9 by jishnub](https://discourse.julialang.org/t/eachindex-x-replacement-for-1-length-x-1-and-similar/81481/9)

---

<div class="post-metadata">

**Author:** ![maxkapur](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maxkapur/32/21208_2.png) [@maxkapur](https://discourse.julialang.org/u/maxkapur)\
**Post date:** [May 24, 2022, 12:11am UTC](https://discourse.julialang.org/t/eachindex-x-replacement-for-1-length-x-1-and-similar/81481/20 "2022-05-24T00:11:24Z")

</div>

> [@pablosanjose](#):
>
> Let me emphasise again what was mentioned by @gustaphe above: remember that all the issue with `AbstractArray` iteration applies to “generic” codebases, i.e. those for which you want the user to be able to plug any weird AbstractArray implementation and have it just work.

I agree with the general thrust of your argument, but my impression is that the reason this and the other thread have gone on for so long is that the terms “generic,” “weird,” and “just work” admit a lot of room for ambiguity. It is evident that many people consider a 0-indexed array implemented via OffsetArrays.jl to be an _essential_ part of their workflow, whereas for others it’s a _weird_ choice given that Julia is a 1-based language. Unfortunately, introducing the novel notion of a “generic” codebase does nothing to clarify these issues.

In my (highly uneducated) opinion, generic code is one of the coolest features of Julia, and I think anyone who codes in Julia should aspire to make their package as “generic” as possible to the extent that doing so doesn’t impede performance or introduce safety issues.

> [@pablosanjose](#):
>
> Otherwise, you might want to restrict the type of array you accept, using e.g. `Base.require_one_based_indexing`, or even just enforce `Array` as an input, instead of `AbstractArray`.

To me, the fact that `Base.require_one_based_indexing` exists implies that any function in a package that _doesn’t_ require 1-based indexing and takes an `AbstractArray`, _must_ support offset arrays. Note that the docs specifically warn about this:

[https://docs.julialang.org/en/v1/devdocs/offset-arrays/#Things-to-watch-out-for](https://docs.julialang.org/en/v1/devdocs/offset-arrays/#Things-to-watch-out-for)

For this exact reason, in my personal code, I typically enforce `Array` as an input.

[Next page](https://discourse.julialang.org/t/eachindex-x-replacement-for-1-length-x-1-and-similar/81481.md?page=2)
