Difference between Array and Vector - julia

Is there a difference between Array and Vector?
typeof(Array([1,2,3]))
Vector{Int64}
typeof(Vector([1,2,3]))
Vector{Int64}
Both seem to create the same thing, but they are not the same:
Array == Vector
false
Array === Vector
false
So, what is actually the difference?

The difference is that Vector is a 1-dimensional Array, so when you write e.g. Vector{Int} it is a shorthand to Array{Int, 1}:
julia> Vector{Int}
Array{Int64,1}
When you call constructors Array([1,2,3]) and Vector([1,2,3]) they internally get translated to the same call Array{Int,1}([1,2,3]) as you passed a vector to them.
You would see the difference if you wanted to pass an array that is not 1-dimensional:
julia> Array(ones(2,2))
2×2 Array{Float64,2}:
1.0 1.0
1.0 1.0
julia> Vector(ones(2,2))
ERROR: MethodError: no method matching Array{T,1} where T(::Array{Float64,2})
Also note the effect of:
julia> x=[1,2,3]
3-element Array{Int64,1}:
1
2
3
julia> Vector(x)
3-element Array{Int64,1}:
1
2
3
julia> Vector(x) === x
false
So essentially the call Vector(x) makes a copy of x. Usually in the code you would probably simply write copy(x).
A general rule is that Array is a parametric type that has two parameters given in curly braces:
the first one is element type (you can access it using eltype)
the second one is the dimension of the array (you can access it using ndims)
See https://docs.julialang.org/en/v1/manual/arrays/ for details.

Vector is an alias for a one-dimensional Array. You can see that in the Julia REPL:
julia> Vector
Array{T, 1} where T
julia> Vector{Int32}
Array{Int32, 1}
Similarly, a Matrix is a 2-dimensional Array:
julia> Matrix
Array{T,2} where T

Related

Singleton vector different from its transpose in Julia

If I define A = [1] I get that A is not equal to A' since they are of different types:
julia> A=[1]
1-element Array{Int64,1}:
1
julia> A'
1×1 LinearAlgebra.Adjoint{Int64,Array{Int64,1}}:
1
julia> A == A'
false
If I define another vector B = [1, 2, 3] and I try to do the products with A'and A I obtain the following output:
B=[1,2,3]
3-element Array{Int64,1}:
1
2
3
julia> B*A'
3×1 Array{Int64,2}:
1
2
3
julia> B*A
ERROR: MethodError: no method matching *(::Array{Int64,1}, ::Array{Int64,1})
...
...
That seems a problem of * operator signature that seems not to accept two Array{Int64,1} as operands while defining another vector C = [4 5] we get:
julia> C=[4 5]
1×2 Array{Int64,2}:
4 5
julia> B*C
3×2 Array{Int64,2}:
4 5
8 10
12 15
So * is defined for operands of types Array{Int64,1} and Array{Int64,2} respectively. Why I cannot multiply a column vector by a singleton vector A but I can using A'?
The answer to this depends on how well you understand linear algebra. Julia follows the conventions of linear algebra for it's array multiplication, if you need to brush up, wikipedia's page is a good source.
It boils down to the fact that your A is a column vector whereas A' is a row vector (like C). Matrix multiplication is defined between (n, k) and (k, m) matrices to produce a (n, m) matrix. Column vectors can sometimes be thought of as (n, 1) matrices, so there's no well defined notion of multiplication between two column vectors.
If you want the dot product, use the dot function (you'll need to do using LinearAlgebra first). If you want an element-wise product, you can use the broadcasting notation, u .* v.
In Julia Vectors are one dimensional Arrays, while the transposition works on two dimensional matrices (Array{T,2} equivalent to Matrix{T})
julia> A=[1]
1-element Array{Int64,1}:
1
julia> collect(A')
1×1 Array{Int64,2}:
1
Since transposition in Julia does not materialize the data and rather holds reference to the original I needed to use collect to actually see what is going on.
When using multiplication on 2-dimensional arrays you are actually using linear algebra operations.
If you want to multiply element-wise use the dot . operator instead:
julia> A .== A'
1×1 BitArray{2}:
1
Note it return an Array rather than a single value.
If you want to multiply element-wise (rather than using linear algebra matrix multiplication) you need to vectorize again:
julia> B.*A
3-element Array{Int64,1}:
1
2
3

Why Array{Float64,1} is not a subtype of Array{Real,1} in Julia?

I'm trying to write a Julia function, which can accept both 1-dimensional Int64 and Float64 array as input argument. How can I do this without defining two versions, one for Int64 and another for Float64?
I have tried using Array{Real,1} as input argument type. However, since Array{Int64,1} is not a subtype of Array{Real,1}, this cannot work.
A genuine, non secure way to do it is, with an example:
function square(x)
# The point is for element-wise operation
out = x.*x
end
Output:
julia> square(2)
4
julia> square([2 2 2])
1×3 Array{Int64,2}:
4 4 4

Why is inv() failing?

When I try and run the inv() function on the example from the Julia documentation (v1.0.3), I get an error. The code is as follows (straight from the docs):
julia> M = [2 5; 1 3]
2×2 Array{Int64,2}:
2 5
1 3
julia> N = inv(M)
ERROR: MethodError: objects of type Array{Float64,2} are not callable
Use square brackets [] for indexing an Array.
It does work with pinv(), but I get some extremely small floating point values. Any ideas why I can't get inv() to work for this extremely simple case?
The error message suggests that you have previously defined a variable called inv which is a floating point matrix, and then try to use this matrix as a function, e.g.
julia> inv = rand(2, 2);
julia> M = [2 5; 1 3];
julia> inv(M)
ERROR: MethodError: objects of type Array{Float64,2} are not callable
Use square brackets [] for indexing an Array.
You can reach the inv function by restarting (and hence clearing the meaning of inv) or using the fully qualified name:
julia> import LinearAlgebra
julia> LinearAlgebra.inv(M)
2×2 Array{Float64,2}:
3.0 -5.0
-1.0 2.0

Julia: Set index at NTuple

Let's say I have an NTuple with 4 entries of Int64 uninitiallized. How do I set the value of each index separately?
I tried the setindex function of base but it didn't work. Any idea?
T = NTuple{4,Int64}
setindex(T,9,2) # set T(2) to 9
You probably meant NTuple{4, Int64} not Ntuple{4, Int64}.
NTuple is a compact way of representing the type tuples having elements of a single type (not actual values but their types; the thing that might be confusing here is that NTuple{4, Int64} is also technically a value that you can bind to a variable, but this is not what you probably want to do given your question).
You can check this by looking up help on it. In your case it represents a type for a tuple of length 4 and all elements of type Int64. For example (1,2,3,4) is such a tuple. You can check it by writing (1,2,3,4) isa NTuple{4, Int64} which will evaluate to true.
Now if you ask why a tuple like (1,2,3,4) does not support setindex! the reason is that tuples are immutable in Julia, see https://docs.julialang.org/en/latest/manual/types/#Tuple-Types-1. This means that you have to assign a value to each field of a tuple upon its construction and it cannot be mutated.
If you want a mutable container you should probably consider using a vector instead of a tuple. For example:
julia> x = Vector{Int}(undef, 4)
4-element Array{Int64,1}:
0
0
0
0
julia> x[2] = 9
9
julia> x
4-element Array{Int64,1}:
0
9
0
0

Julia multidimensional array types?

I have an array of type Array{Float64,2} but it's an array of 1 column, and I'm unable to pass this into a function that's expecting a single-column array of type Array{Float64,1}. I don't really understand what the 2 means or how to fix my problem, and I haven't been able to figure it out by searching through any documentation.
In Array{Float64,2}, the 2 is the number of dimensions in the array. Since you say it's "it's an array of 1 column", you probably have something which is 2-dimensional with either one row or one column, i.e. one of
julia> c = rand(1,3)
1x3 Array{Float64,2}:
0.190944 0.928697 0.251519
julia> d = rand(3,1)
3x1 Array{Float64,2}:
0.0818493
0.0342291
0.58341
To turn this into a 1-dimensional array, you could slice the array manually or use squeeze, as you prefer:
julia> c[1,:]
3-element Array{Float64,1}:
0.190944
0.928697
0.251519
julia> squeeze(d,2)
3-element Array{Float64,1}:
0.0818493
0.0342291
0.58341
Either approach should give you something of type Array{Float64,1}.
As noted in the comments, another approach is to use reshape, e.g. (using a different random c):
julia> reshape(c, length(c))
3-element Array{Float64,1}:
0.680653
0.0573147
0.607054
This has the advantage -- and disadvantage -- of not caring whether you have an array of shape 1xN or Nx1.

Resources