Enumerate loop: problem with indexing (method error)


Good afternoon,
Using an enumerate loop, I get an error method when trying to fill in a vector with value calculated at each iteration of the loop. Would anyone know how to solve it? Many thanks for your help.

grid = collect(range(0.01, length=3, stop=1.0))   
  X= Vector  
for (i, D) in enumerate(grid)
    X[i] = i * D
MethodError: no method matching setindex!(::Type{Array{T,1} where T}, ::Float64, ::Int32)

 [1] top-level scope at .\In[95]:4


Your X is not a Vector but a UnionAll, since you assigned X to be the type Vector, not an instance of it as you could with X = Vector().
But that gives you an empty vector which you can’t access with X[i], instead you can push!(X, i*D) to put i*D in X.
Even better, you allocate a vector of the correct length with X = Vector{Float64}(undef,3) and then fill in the values just as you did with the loop. This generally gives the best performance since you don’t have to allocate a new vector within the loop, only preallocate it once beforehand.



Wonderful Peter. You solved it so fast. many many thanks. Also your explanation is useful to avoid this type of errors in the future. Have a nice day!


Firstly, there is no need to collect your range. In fact you should almost never do that, unless you have a very specific need. (For some reason, everyone wants to collect ranges all the time. Please don’t :smile: )

Secondly, here, I think a comprehension would be a very nice solution, and you don’t have to specify the type. Then your code becomes:

grid = range(0.01, length=3, stop=1.0)  # don't collect here!
X = [i * D for (i, D) in enumerate(grid)]

You could also try:

X = eachindex(grid) .* grid