ERROR: LoadError: BoundsError: attempt to access 10-element Vector{Int64} at index [11]

Hello,
The contents of the file.txt file is as follows:

1 2 3 4 5 6 7 8 9 10

I wrote the following code to put the numbers in the file into an array:

function arrayandfile()
    array = fill(0,10)
    inn = open("file.txt","r")
    counter = 1
    while !eof(inn)
        c = read(inn,Char)
        if c != ' '
            array[counter] = parse(Int,c)
            counter +=1
        end
    end
    return(array)
end
println(arrayandfile())

Which part of the code is wrong?

Thank you.

Probably the part that thinks that “10” is one character and not a “1” followed by a “0”.

Hello,
Thank you so much for your reply.
The read function interprets the number 10 as 1 and 0 instead of 10.
What is the solution?

GunnarFarneback is right. In this case, I would recommend that you just read in the entire txt file and then process certain lines in it as needed. That’s how I got it when I did Atcoder.

data_str = read(joinpath(@__DIR__, "file.txt"), String)
lines = split(data_str, "\n", keepempty=false)
array = parse.(Int, split(lines[1]))

When dealing with data like 1 2 3 4 5 6 7 8 9 10, first read the line in its entirety and then separate all the numbers with the split(), which is the Julia style of writing. Your writing style is somewhat like C.

You could also use readlines (or eachline).


By the way, the title of the thread is wrong/misleading: you’re attempting to access an X-element Vector{Int64} at index [X + 1] (for X == 10). As Julia is 1-indexed, accessing at index X == length(...) is completely fine.

Hello,
Thank you so much for your reply.
I changed the code as follows:

function arrayandfile()
    array = fill(0,10)
    counter = 1
    for line in eachline("file.txt")
        if line != ' '
            array[counter] = parse.(Int, split(line))
            counter +=1
        end
    end
    return(array)
end
println(arrayandfile())

I got:

ERROR: LoadError: MethodError: Cannot `convert` an object of type Vector{Int64} to an object of type Int64

What’s happening here is that parse.(Int, split(line)) gives you a Vector{Int} (namely, [1, 2, ..., 10]), which you’re trying to assign to the single Int at array[counter].

You could use

function arrayandfile()
    array = fill(0, 10)  # where 10 is the total number of values in the file
    counter = 0          # number of values actually put in array so far
    for line in eachline("file.txt")
        line_values = parse.(Int, split(line))
        array[counter + 1 : counter + length(line_values)] .= line_values
        counter += length(line_values)
    end
    
    return array
end

I’ve removed the line != ' ' check, as

  1. it’s no longer necessary as split takes care of the spaces
  2. line, being a String, will never equal ' ' (also note that " " != ' ').

You could also go full-on vectorisation and write this as a one-liner

reduce(vcat, parse.(Int, split(line)) for line in eachline("file.txt"))

E.g.

julia> reduce(vcat, parse.(Int, split(line)) for line in eachline(IOBuffer("1 2 3\n4 5 6 7 8\n9 10")))
10-element Vector{Int64}:
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10

Thanks again.
I’m a newbie and your code is a little difficult for me to understand.

1- If counter=1, then the line array[counter] = parse.(Int, split(line)) places the number 1 in cell 1 of the array. Am I right?

2- I changed the code as follows, removed the (counter) and the problem was fixed:

function arrayandfile2()
    array = fill(0,10)
    for line in eachline("file.txt")
        if line != ' '
            array = parse.(Int, split(line))
        end
    end
    return(array)
end
println(arrayandfile())

Why?

No. The dot at the end of parse. means we are broadcasting the parse statement, resulting in a Vector. So the left-hand side of the assignment is an Int, but the right-hand side is a Vector{Int}.

One of the neat aspects of Julia is its interactivity in the REPL. You could debug by just checking all variables involved, via

julia> array = fill(0,10)
10-element Vector{Int64}:
 0
 0
 0
 0
 0
 0
 0
 0
 0
 0

julia> counter = 1
1

julia> line = first(eachline(IOBuffer("1 2 3 4 5 6 7 8 9 10")))  # or your file
"1 2 3 4 5 6 7 8 9 10"

julia> line != ' '
true

julia> array[counter] = parse.(Int, split(line))
ERROR: MethodError: Cannot `convert` an object of type Vector{Int64} to an object of type Int64
The function `convert` exists, but no method is defined for this combination of argument types.

Closest candidates are:
  convert(::Type{T}, ::T) where T<:Number
   @ Base number.jl:6
  convert(::Type{T}, ::T) where T
   @ Base Base.jl:126
  convert(::Type{T}, ::AbstractChar) where T<:Number
   @ Base char.jl:185
  ...

Stacktrace:
 [1] setindex!(A::Vector{Int64}, x::Vector{Int64}, i::Int64)
   @ Base .\array.jl:987
 [2] top-level scope
   @ REPL[5]:1

julia> array[counter]
0

julia> split(line)
10-element Vector{SubString{String}}:
 "1"
 "2"
 "3"
 "4"
 "5"
 "6"
 "7"
 "8"
 "9"
 "10"

julia> parse.(Int, split(line))
10-element Vector{Int64}:
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10

julia> typeof(array[counter])
Int64

julia> typeof(parse.(Int, split(line)))
Vector{Int64} (alias for Array{Int64, 1})

Alternatively, you could also of course use something like Debugger.jl, though I find it a bit harder to get used to.

Now within each iteration step you’re creating a new variable called array holding our Vector{Int} from the parse.. This will work in this case, but not if you have multiple lines. Only the value in the last iteration step will be returned.

Good questions.

for line in eachline("file.txt") in each iteration, line is a string of all the characters in that line, a string that"1 2 3 4 5 6 7 8 9 10",

then split(line) gives you

10-element Vector{SubString{String}}:
 "1"
 "2"
...
 "9"
 "10"

parse.(Int, split(line)) gives you

10-element Vector{Int64}:
  1
  2
...
  9
 10

This is a vector of length 10, instead of receiving it with array[counter], use array = parse.(Int, split(line)). What you wrote in the second question is correct, but limited to the file being only one line.

Want to know if a file has multiple lines?
If there’s something else you don’t understand, go ahead and ask a question.

Thanks again.
Your answer raised a few questions for me:

1- Does the following method fix broadcasting?

save = parse.(Int, split(line))
array[counter] = save

2- Can you explain Vector to me in simple terms?

Hello,
Thank you so much for your reply.
I can’t understand Vector!

A vector is an elementary mathematical concept that represents a directed line segment. The mathematical notation is denoted as v.

The length of the projection of a vector on each axis is the vector’s component. e.g. v = [1,2,3].
Clearly, the components of a vector are scalars.

What is called the dimension of a vector in mathematics refers in programming to the length of the vector, i.e., the number of components of the vector. length(v)=3

Here are some common uses of vectors in julia.

v=[1,2,3] # typeof(v)=Vector{Int64}
v[1]=10 # now v=[10,2,3]
v[2:3]=[4,6] # now v=[10,4,6]
v2=dot(v,v) # cross product of vectors
v3=v.*v # dot product of vectors

Vector is just one-dimensional array. see doc Base.Vector e.g., Vector{T} is alias for Array{T, 1} where T is type of elements it holds and 1 means it’s one dimensional.

# Creating vectors
numbers = [1, 2, 3, 4, 5]       # Using square brackets
empty_vector = Vector{Int}(undef, 3)  # Creates uninitialized vector of 3 integers
zeros_vector = zeros(5)         # Creates [0.0, 0.0, 0.0, 0.0, 0.0]
string_vector = ["apple", "banana", "cherry"]

you can try with Julia one-liner style:

arrayandfile(filename) = parse.(Int, split(read(filename, String))) # Read entire file content and return the vector

I doubt invoking linear algebra is the easiest way to explain the notion of Vector in Julia :slight_smile:. (Also, I’d define a mathematical vector simply as an element of a vector space, which in turn is a triple consisting of a set and two operations, satisfying certain properties.)

If you insist on referring to mathematics, a Vector{Int} of length N \in \mathbb{N} is just an element of \mathbb{Z}^N (if you ignore the differences between \mathbb{Z} and the set of Ints).
By the way, note that \mathbb{Z}^N is not a vector space, though it is a subset (and subgroup) of the vector space \mathbb{R}^N. Something like a Vector{String} clearly also does not correspond to some vector space.


I would just explain a Vector as a finite sequence of ‘things’. A Vector{Int} is a finite sequence of Ints, a Vector{String} a finite sequence of Strings, a Vector{Any} a finite sequence of whatever your heart desires.

  • Obviously dot(v, v) is the dot (inner) product of v with itself (a.k.a. v ⋅ v ). The result is a scalar (Int here). To be able to use dot and you first need to import LinearAlgebra.
  • v .* v is the elementwise product of v with itself. The result is a Vector satisfying (v .* v)[i] == v[i] * v[i] for i \in \{1, 2, 3\}.
  • cross(v, v) (v × v) is the cross product of v with itself. In general, for two Vectors v and w of length 3, v × w is another Vector of length 3. But v × v consists of zeros. You need to import LinearAlgebra to use cross and ×.

Again no. (Also, broadcasting is a proper, awesome feature, not a bug. It does not need fixing :slight_smile: .)
You can view

save = parse.(Int, split(line))  # Note the dot .

as shorthand for

splt = split(line)
save = Vector{Int}(undef, length(splt))
for i = 1:length(splt)
    save[i] = parse(Int, splt[i])  # Note there's no dot
end

Then array[counter] = save attempts to put this entire Vector{Int} save (a sequence of 10 Ints) into array[counter] where we have room for only a single Int. So this will cause an error.

Hello,
Thank you so much for your reply.
Do you mean that 10 is not a single Int?

What is the solution?

Hello,
When I define an array using array = fill(0,10), what is the maximum number each cell of the array can hold?

The word “ten” has three letters (or characters) in it; t, e, n. The text “10” has two characters: 1, 0. The roman numeral “X” is just one letter. All are ways of writing down and communicating a particular idea to humans — once we read it we get the concept of a single number in our minds.

Julia — and nearly all programming languages — have a distinction between strings (sequences of characters like "ten" and "10") and numbers (without quotes: 10). When you parse a bit of text (a String) into an Int, you’re doing the work to interpret that text as a number. It’s a single value at that point, and it could be as large as a few quintillions (or negative, too).

Hello,
Thank you so much.
The result of parse.(Int, split(line)) is:

10-element Vector{Int64}:
  1
  2
...
  9
 10

Here, the number 10 is of type Int. Here 10 should be 10, not 1 and 0. I don’t understand why it doesn’t fit in the array cell!