# Any shortcut to 1:length(myVector)?

Is there any build-in function in Julia to replace `1:length(myVector)`, i.e. to return a vector of integers from 1 to the length of `myVector` ?

e.g.:

``````myVector =["a","b","c"]
for i in ???(myVector)
println(i) # 1,2,3
end
``````

There is `eachindex`.

``````julia> myVec = ["a","b","c"];

julia> for i in eachindex(myVec)
println(i)
end
1
2
3
``````

Note, however, that this doesn’t necessarily give integers but whatever is appropriate/fast to index `myVec` with.

21 Likes

`1:length` is pretty short, just 8 characters. Also, it isn’t normally what you should be using, not for indexing, at least.

In a way, `1:length` is a bit of an ad-hoc pattern, which probably shouldn’t have it’s own function, imho.

1 Like

There is also

``````for i in firstindex(x):lastindex(x)
println(i)
end
``````

which has the advantage of supporting offset arrays.

1 Like

Is this ever different from `eachindex`?

Apparently yes, it always returns integers (example adapted from here):

``````julia>  A = [1, 2, 3, 4];

julia> B = view(A,1:2,1:1)
2×1 view(::Array{Int64,2}, 1:2, 1:1) with eltype Int64:
1
2

julia> for i in eachindex(B)
println(i)
end
CartesianIndex(1, 1)
CartesianIndex(2, 1)

julia> for i in firstindex(B):lastindex(B)
println(i)
end
1
2

``````
3 Likes

Maybe `LinearIndices`, then:

``````for i in LinearIndices(B)
println(i)
end

1
2
``````
5 Likes

@leandromartinez98, for offset arrays, don’t we have to use `pairs` to obtain the offset indices? Example:

``````using OffsetArrays
A = [1 2 3; 4 5 6];
B = OffsetArray(A,-1:0,0:2)
for (i,) in pairs(B)
println((i,i))
end
(-1, 0)
(0, 0)
(-1, 1)
(0, 1)
(-1, 2)
(0, 2)
``````

Afaik `getindex(::OffsetArray, ::Int)` works fine, it’s only `OffsetVectors` for which integer indexes are ambiguous. `eachindex` should always work, because it takes care of this, ie

``````julia> A = OffsetArray(1:2, 3:4)
1:2 with indices 3:4

julia> B = OffsetArray(reshape(1:6, 2, 3), -1:0, 0:2)
2×3 OffsetArray(reshape(::UnitRange{Int64}, 2, 3), -1:0, 0:2) with eltype Int64 with indices -1:0×0:2:
1  3  5
2  4  6

julia> eachindex(A)
OffsetArrays.IdOffsetRange(3:4)

julia> eachindex(B)
Base.OneTo(6)
``````
3 Likes

I think things are getting mixed up here. But the OP wanted a way to obtain a vector of integers of the indexes of an array (I guess one-dimensional). `firstindex` and `lastindex` will do the job for offset arrays (as eachindex, but this one may return something that is not the indexes exactly, I am not sure how often and which are the collections for which that does not happen).

``````julia> using OffsetArrays

julia> x = OffsetArray([1, 2, 3],0:2)
3-element OffsetArray(::Array{Int64,1}, 0:2) with eltype Int64 with indices 0:2:
1
2
3

julia> for i in firstindex(x):lastindex(x)
println(i)
end
0
1
2

``````

By the way, although I think the OP knows that, the original question was how to obtain a vector of the indexes of an array.

Perhaps just for the sake of completeness:

``````julia> x = ["a","b","c"]
3-element Array{String,1}:
"a"
"b"
"c"

julia> indexes = collect(eachindex(x))
3-element Array{Int64,1}:
1
2
3

``````

One thing that motivated my original mention of `firstindex` and `lastindex` was that I was not sure that `eachindex` necessarily returned the range in order. (the notation eachindex perhaps suggests that it does not, and that the iterations could occur out of order if that resulted to be more efficient for some reason. Apparently there is such guarantee?

There’s also `enumerate()`, which returns a tuple containing your incrementing index and the the value from `myVector` at that index. Useful if you’re wanting to both go through myVector and get the index for other reasons at the same time.

Note how I had to unpack the tuple in the for-loop with the `()`'s around `i` and `x`.

``````myVector =["a","b","c"]
for (i, x) in enumerate(myVector)
println("\$i: \$x")
end

# output:
# 1: a
# 2: b
# 3: c
``````
2 Likes

I would like to note that `enumerate` documentation says:

An iterator that yields `(i, x)` where `i` is a counter starting at 1, and `x` is the ith value from the given iterator. It’s useful when you need not only the values `x` over which you are iterating, but also the number of iterations so far. Note that `i` may not be valid for indexing `iter`; it’s also possible that `x != iter[i]`, if `iter` has indices that do not start at `1`. See the `pairs(IndexLinear(), iter)` method if you want to ensure that `i` is an index.

So it has nothing to do with indexes, and it will give you incorrect index values if you are using any “non-vanilla” array. It is just a convenience for the cases in which you wanted to have a counter being incremented at each iteration.

3 Likes

This is slightly off topic but I have often used `for (index,value) in enumerate(X)` to create a loop where I need both the index and the value to work with. This has been fine for default arrays and I haven’t had an issue. It would be neat eventually to have a version that worked with arbitrarily indexed arrays by returning the value and the same indices returned by `eachindex(X)`

At the same time I’ve been reducing my usage of this pattern using broadcast and higher-ordered functions.

That’s `pairs` as noted above.

11 Likes

(sorry, this was a reply to Henrique_Becker’s comment on my post.)

My fav (not yet mentioned) `for i in axes(myVector,1)`

6 Likes

Since functions are first class citizens in Julia, you can always create yours:

``````julia> inds(x) = firstindex(x):lastindex(x) |> collect;

julia> myVector =["a","b","c"];

julia> inds(myVector)
3-element Array{Int64,1}:
1
2
3
``````
1 Like

Mind blown, I knew about `pairs` but only had it in my mind in the context of Dictionaries. Using it for arrays is awesome!

I recently started to use `keys` for this:

``````for i in keys(myVector)
...
end
``````

The added benefit is there is no need to touch that even if I change the underlying container type.

2 Likes

Note that if you don’t just need the indexes, but are lookup up the corresponding element (`myVector[i]`), `pairs` may be efficient for some collections.

1 Like