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”.

2 Likes

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.

2 Likes

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.

3 Likes

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.

2 Likes

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.

1 Like

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
1 Like

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
2 Likes

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 ×.
3 Likes

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.

1 Like

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).

3 Likes

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!