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
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.
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.
There is also
for i in firstindex(x):lastindex(x)
println(i)
end
which has the advantage of supporting offset arrays.
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
Maybe LinearIndices
, then:
for i in LinearIndices(B)
println(i)
end
1
2
@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[1],i[2]))
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)
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
I would like to note that enumerate
documentation says:
An iterator that yields
(i, x)
wherei
is a counter starting at 1, andx
is the ith value from the given iterator. It’s useful when you need not only the valuesx
over which you are iterating, but also the number of iterations so far. Note thati
may not be valid for indexingiter
; it’s also possible thatx != iter[i]
, ifiter
has indices that do not start at1
. See thepairs(IndexLinear(), iter)
method if you want to ensure thati
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.
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.
Thanks for the clarification. Hadn’t thought about that aspect of it.
(sorry, this was a reply to Henrique_Becker’s comment on my post.)
My fav (not yet mentioned) for i in axes(myVector,1)
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
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.
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.