Arrays, vectors, and matrices in Engee
Introduction
For working with data, parameters, and complex structures in Engee arrays, vectors, and matrices are used. These structures are implemented in the language Julia, allows you to efficiently store and process numerical information, including calculation results, signals, and model parameters. This article discusses the specifics of each of them.
In Julia, the numbering of elements of arrays, vectors, and matrices begins with 1, and not with 0 as in some other languages. The last element has an index end. This corresponds to mathematical traditions, where indexing also starts with one. For example, the first element of the array a = [1, 2, 3] available via a[1], and the last one is through a[end]. For more information, see the section below.
|
An array is a generalized multidimensional container that can contain elements of any type. Arrays in Julia support an arbitrary number of dimensions, which makes them a universal tool for storing and working with data.:
A = rand(2, 2, 3)
Output
2×2×3 Array{Float64, 3}:
[:, :, 1] =
0.159525 0.787948
0.358068 0.124023
[:, :, 2] =
0.228296 0.292929
0.712896 0.0253828
[:, :, 3] =
0.3547 0.837655
0.474441 0.201402
Arrays can be dynamic or static.:
-
Dynamic arrays are arrays whose size can change during program execution. They are stored in memory with possible expansion, which makes them more flexible but less optimal for computationally intensive tasks.
Example:
dynamic_array = [1, 2, 3] dynamic_array[2] = 5 # Присваивание значения push!(dynamic_array, 4) # Добавление элемента deleteat!(dynamic_array, 3) # Удаление элемента с индексом 3Output
4-element Vector{Int64}: 1 5 3 4 -
Static arrays are arrays of a fixed size, which is set at the creation stage. They are stored in memory as a continuous block of data, which allows operations to be performed faster by minimizing the overhead of memory management.
Static arrays are effective when their size is less than 100-200 elements. If the size is more than 100-200 elements, then dynamic arrays are usually used. In Julia, static arrays are provided by the StaticArrays.jl package. Therefore, in order to use them, you must connect this package using the command
using StaticArrays.Example:
using StaticArrays static_array = @SVector [1, 2, 3]Output
3-element SVector{3, Int64} with indices SOneTo(3): 1 2 3The macrofootnote was used in the code:[Macros in Julia are special constructions starting with the symbol
@, which transform the code before executing it.]@SVector, which creates a static one-dimensional array (vector) of fixed size. There are other useful macros for static arrays.:Macros for static arrays_
-
@SVector— creates an immutable static vector of fixed size. Example:@SVector [1, 2, 3]. -
@MVector— creates a mutable static vector of fixed size. Example:@MVector [1, 2, 3]. -
@SMatrix— creates an immutable static matrix of fixed size. Example:@SMatrix [1 2; 3 4]. -
@MMatrix– creates a mutable static matrix of a fixed size. Example:@MMatrix [1 2; 3 4]. -
@SizedArray— converts a regular array into a static array with a fixed size. Example:@SizedArray rand(2, 2). -
@SArray— creates a shared immutable static array, which can be a vector, a matrix, or an array of larger dimensions. Example:@SArray rand(2, 2, 2). -
@MArray— creates a shared mutable static array. Example:@MArray rand(2, 2, 2). -
@StaticArray— a universal macro that creates immutable arrays of any shape. Example:@StaticArray rand(2, 2). -
@MutableStaticArray— a universal macro for creating mutable static arrays. Example:@MutableStaticArray rand(2, 2). -
@zeros— creates a static array filled with zeros. Example:@zeros(SVector, 3)creates a vector of three zeros. -
@ones— creates a static array filled with units. Example:@ones(SMatrix, 2, 2)creates a 2x2 matrix of units. -
@fill— creates a static array filled with the specified value. Example:@fill(SVector, 3, 42)creates a vector of three elements with a value of 42. -
@static— optimizes the execution of code blocks at the compilation stage by applying the properties of static arrays.Example:
@static if length(SVector(1, 2, 3)) == 3 println("Размер вектора равен 3") end
-
|
Unlike in C++, arrays in Julia can store elements of different types. If the types of elements can be reduced to a common one (for example
If the element types cannot be reduced to a common one (for example, a number and a string), then Julia will convert the array to the type
This makes arrays flexible in Julia, but it’s worth remembering that using |
A vector is a one—dimensional array that represents a sequence of elements that are accessed using indexes. In Julia, a vector can be created as a column vector or a row vector, but their syntax and data type will differ.:
-
A column vector is created using commas or column entries.:
v = [1, 2, 3] # Вектор-столбецor
v = [1 2 3] # Вектор-столбецOutput
3-element Vector{Int64}: 1 2 3 -
In Julia, there is no separate type for a string vector. Instead, a string of numbers is represented as a 1 × N matrix.:
r = [1 2 3] # Матрица 1 × 3Output
1×3 Matrix{Int64}: 1 2 3
|
In Julia, delimiters in arrays define their structure:
|
A matrix is a two—dimensional array representing a table of numbers or other objects organized into rows and columns. In Julia, matrices are created as arrays with two dimensions:
M = [1 2 3; 4 5 6]
Output
2×3 Matrix{Int64}:
1 2 3
4 5 6
The division into vectors and matrices in Julia allows you to efficiently organize data in memory, which is important for fast numerical calculations. Vectors use one-dimensional storage, making it easier to work with sequences of data, while matrices are organized in two-dimensional form, which makes it easier to perform linear algebra (multiplication and transposition). This separation helps optimize the use of cache memory and processor resources, making calculations more productive.
Differences between arrays, vectors, and matrices
Dimension:
-
An array is a container with an arbitrary number of dimensions. Arrays have an arbitrary number of dimensions, and
size(A)it can return, for example, (2,2,3). -
A vector is a one—dimensional array. Vectors always have the same dimension, and the function
size(v)returns a tuple(n,), wheren— the length of the vector. -
The matrix is a two—dimensional array. The matrices have a dimension of two, and
size(M)returns a tuple(n, m), wheren— the number of lines, andm— the number of columns.
|
A tuple is an immutable data structure that can contain several elements of various types. In Julia, tuples are used to represent values that are logically related but do not require modification. For example, the result of the function Unlike a vector and a matrix, a tuple is not an array and is not intended for performing arithmetic operations. It has a fixed number of elements and an immutable structure, which makes it useful for returning multiple values from functions or passing parameters. |
-
Implementation features:
-
Methods and functions for working with arrays are applicable to both vectors and matrices. However, each data type has its own optimized algorithms.
-
In Julia, vectors and matrices are special cases of arrays, where the vector has dimension
1, and the matrix —2.
-
-
Initialization and syntax:
-
An array with an arbitrary dimension is created by the Array function or using generators (expressions in the form
[… for …]). For example, for Array:A = Array{Float64}(undef, 2, 2, 3)Here, undef is a keyword used to create an array without initializing the elements. This means that the memory for the array will be allocated, but the values of its elements will remain undefined (they may be random).
An example with generators:
array = [i^2 for i in 1:5] # Каждый элемент массива – квадрат числа от 1 до 5 -
The vector is created as a one-dimensional array, the elements are separated by commas.:
v = [1, 2, 3] -
The matrix is written as lines separated by semicolons (
;), and the elements in the lines are separated by spaces or tabs:M = [1 2 3; 4 5 6]
-
-
Storage in memory:
-
Arrays with a large number of dimensions use a more general approach to data storage, which can increase overhead when performing operations.
-
The differences described above shape specific application areas.:
-
The array is used to model more complex data: three-dimensional models, arrays of images, or multidimensional time series.
-
A vector is most often used for one-dimensional data: time series, coordinates, and signals.
-
The matrix represents two-dimensional structures: images, tables, and systems of linear equations.
Basic functions for working with arrays, vectors, and matrices
Julia provides a wide range of functions for working with arrays, including vectors and matrices. For more information about functions and their signatures, see Arrays.
|
Functions marked with a symbol
The operators are used to provide access to the elements of such functions |
Below is a list of the main functions with a brief description and examples.:
Creation
Function name |
Description |
Example |
|
Creates an array with elements equal to zero. The type of object being created depends on the arguments passed: a one-dimensional array (vector), a two-dimensional array (matrix), or a multidimensional array. |
here:
|
|
Creates an array with elements equal to one. The type of object being created depends on the arguments passed: a one-dimensional array (vector), a two-dimensional array (matrix), or a multidimensional array. |
here:
|
|
Creates an array filled with random numbers with a uniform distribution in the interval |
here:
|
|
Creates an array filled with the specified value. The type of object being created depends on the arguments passed: a one-dimensional array (vector), a two-dimensional array (matrix), or a multidimensional array. |
here:
|
|
Creates an array by converting a specified range or an iterable object. The type of object being created depends on the input used. |
here:
|
The change in structure
Function name |
Description |
Example |
|
Adds an element to the end of a one-dimensional array (vector). Applicable only to mutable (dynamic) arrays. The end index ([indexing]) can also be used to add an element. |
here:
|
|
Deletes and returns the last element from a one-dimensional array (vector). Applicable only to mutable (dynamic) arrays. |
here:
|
|
Inserts an element into the specified position of a one-dimensional array (vector). Applicable only to mutable (dynamic) arrays. |
here:
|
|
Deletes an element at the specified index from a one-dimensional array (vector). Applicable only to mutable (dynamic) arrays. |
here:
|
working with dimensions
Function name |
Description |
Example |
|
Returns the size of an array, matrix, or vector in the form of a tuple, where each value corresponds to the size of a specific dimension. |
here:
|
|
Modifies the size of a one-dimensional array (vector). If the new size is larger than the current one, the new elements are initialized to the default value. |
here:
|
|
Returns the total number of elements in an array, vector, or matrix, regardless of their dimension. |
here:
|
|
Returns the number of dimensions (dimensions) of an array, vector, or matrix. |
here:
|
|
Modifies the dimension of an array, matrix, or vector, converting it into a new array with the specified number of rows and columns. The number of elements in the new array must match the number of elements in the original one. |
here:
|
linear algebra
Function name |
Description |
Example |
|
Returns a transposed array or matrix where rows are swapped with columns. For a one-dimensional array (vector), the result depends on its orientation. |
here:
|
* |
Calculates the determinant of a square matrix. It is part of the LinearAlgebra package (requires installation of the package). A determinant is a scalar quantity that characterizes the properties of a matrix (for example, its reversibility). |
here:
|
|
Calculates the inverse matrix for a square matrix. The inverse matrix exists only for matrices with a nonzero determinant, that is, for those that are invertible. Function |
here:
|
* |
Calculation of eigenvalues and matrix vectors. For example:
|
here:
|
|
Calculates the norm of a vector or matrix. A norm is a numerical characteristic that measures «size» vectors or matrices. By default, the Euclidean norm is calculated. |
here:
|
check
Function name |
Description |
Example |
|
Checks whether an array, vector, or matrix is empty. Returns |
here:
|
|
Checks whether the object is null. Returns It supports numeric types, as well as arrays, matrices, and vectors (in Julia, an object is considered null if all its elements are zero). |
here: For numbers:
For vectors:
For matrices:
For multidimensional arrays:
|
|
Checks whether the matrix is symmetric. Returns |
here:
|
conversion
Function name |
Description |
Example |
|
Converts a matrix or a multidimensional array into a vector. It returns a one-dimensional array in which the elements are taken from the columns of the original matrix or array. If the argument is already a vector, then it is returned unchanged. |
|
|
Rearrangement of dimensions (axes) of a multidimensional array. Allows you to change the order of measurements without changing the data itself, creating a new array with rearranged axes. |
here:
|
|
Horizontal and vertical combining of arrays (Concatenation).
|
here:
|
|
creates an independent copy of an array, vector, or matrix. Changes made to the copy do not affect the original object and vice versa. |
here:
|
|
creates a deep copy of the array, recursively copying all nested structures. Changes to the copy do not affect the original. In Julia, the default assignment does not pass a value, but a reference to an object. If you need to create an independent copy, there are two ways.:
|
here:
|
|
Allows you to perform operations on array elements with automatic size matching (broadcasting). For more information, see here. |
here:
|
The relevance of using arrays
Arrays are a convenient and flexible tool for working with data, but Julia has other structures that may be better suited for certain tasks. For more information, see below.
When arrays are recommended
-
Quick access to elements by index — Arrays store elements sequentially in memory, which allows instant access to any element by its index. For example,
arr[3]it will immediately return the third element of the array. It’s called random access, and it works in time.O(1)(the operation is performed in constant time, regardless of the size of the input data, that is, accessing the element by index takes the same time, regardless of how large the array is). -
Efficient adding and removing at the end — if you need to add or remove items at the end of an array frequently, then use the functions
push!(add an element) andpop!(delete the last element). These operations are performed very quickly, as they do not require rearranging other elements. -
Working with a fixed amount of data — if you know in advance how many elements will be stored, arrays work especially efficiently. They allocate memory immediately, which minimizes the overhead of resizing.
-
Vector computing and linear Algebra — Julia is optimized for working with arrays, especially numeric ones. If you work with matrices, vectors, or perform linear algebra operations, arrays are the best choice. For example, functions for working with matrices such as
dot,cross, or operations with arrays via broadcast (.+,.*), they work faster with arrays.
When arrays are not recommended
-
Frequent addition or deletion of elements in the middle or beginning — if you need to frequently insert or delete elements at the beginning or middle of the array. For example, the functions
insert!(insert) anddeleteat!(deletion) requires shifting all subsequent elements, which makes them inefficient for large arrays. Alternative: useDequefrom the packageDataStructures.jl, which is optimized for insertion and deletion at both ends. -
Search for elements by key — if you need to quickly find elements by unique keys (for example, by username or ID), arrays are not suitable, because they search through all the elements (which is quite a long time). Alternative: use
Dict(dictionary), which allows you to quickly find items by key. -
Frequent resizing of the structure — if the data structure changes frequently (for example, elements are added or deleted in arbitrary places), arrays will be ineffective. Alternative: consider using
Set,Dictor list structures such asListfrom the package DataStructures.jl. -
Working with immutable data — arrays in Julia are mutable, meaning their elements can be changed after creation. If you need an immutable data structure, it is better to use tuples. They do not allow you to change their elements, which makes them convenient for storing constant data. For example:
t = (1, 2, 3) t[1] = 10 # Ошибка! Кортежи неизменяемы
Arrays, matrices, and vectors of strings and characters
In Julia, arrays, matrices, and vectors can contain strings or characters, as well as numbers.
# вектор строк
v = ["apple", "banana", "cherry"]
println(v[1]) # apple
# Матрица символов
m = ['a' 'b'; 'c' 'd']
println(m[1, 2]) # b
# Трехмерный массив строк
a = [["a", "b"], ["c", "d"]]
println(a[1][2]) # "b"
-
A vector of strings — each string is stored as an element of a one-dimensional array.
-
The symbol matrix is a two—dimensional array where each element is a symbol.
-
Three—dimensional array of strings - supports an arbitrary number of dimensions with text data.
Arrays in Julia are dynamic by default, but their length is fixed until explicitly changed. This means that when creating an array, its current length remains unchanged until special methods are used, such as push!, append! or resize!. This is done to improve performance: fixed-length operations are faster because they do not require constant memory reallocation.
More complex constructions with end, such as end+1, do not allow you to directly assign a value to an array element, since such operations go beyond the current length. To add new elements, you need to explicitly increase the size of the array. For example, you can use resize!:
a = [10, 20, 30]
resize!(a, length(a) + 1) # Расширяем массив на 1 элемент
a[end] = 40 # Присваиваем значение новому элементу
println(a) # [10, 20, 30, 40]
Constructions with end They are available for indexing and performing arithmetic operations with indexes inside existing array boundaries. For example:
-
a[end]— access to the last item. -
a[end-1]— access to the second element from the end. -
a[1:end]— getting the entire array. -
a[1:end-1]— getting all the items except the last one.
In Julia, you cannot directly assign a value to an element with an index end+1 or any index beyond the current length of the array. To change the size of an array, you must use special methods such as resize!, push! or append!.
|
Indexing arrays
Indexing in Julia starts with one, meaning the first element of the array has an index 1. A special index is also supported. end, which indicates the last element of the array or the size of the corresponding dimension. Indexing example:
a = [10, 20, 30, 40]
println(a[1]) # 10 — первый элемент
println(a[end]) # 40 — последний элемент
# Индексация матриц
m = [1 2; 3 4]
println(m[1, end]) # 2 — последний элемент первой строки
-
Index
1always points to the first element. -
endIt is used to refer to the last element in one-dimensional and multidimensional arrays. -
For matrices, the first index is the row number, the second is the column number.
Other variations of indexing:
-
You can access multiple array elements at once using ranges:
b = [1, 2, 3, 4, 5] println(b[2:end]) # [2, 3, 4, 5] — элементы со второго до последнего -
Selecting elements with a specific step:
b = [1, 2, 3, 4, 5] println(b[1:2:end]) # [1, 3, 5] — элементы с шагом 2In Julia, expressions like
1:2:endThey are called ranges. A range is a structure that describes a sequence of numbers with a beginning, a step, and an end. For example,1:2:5creates a sequence from 1 to 5 in steps of 2:[1, 3, 5].In this example
1:2:endspecifies that the selection starts from the first element of the array (1), goes in increments2and ends at the last element of the array (`end`Ranges are used for convenient and efficient work with indexes of arrays and matrices. Examples of using ranges:# Простые диапазоны r1 = 1:5 # Создает последовательность [1, 2, 3, 4, 5] r2 = 1:2:10 # Создает последовательность [1, 3, 5, 7, 9] # Использование диапазона для индексации a = [10, 20, 30, 40, 50] println(a[2:4]) # [20, 30, 40] println(a[1:2:end]) # [10, 30, 50] # Диапазон с "end" println(a[3:end]) # [30, 40, 50] -
Selecting elements that meet certain conditions (for more information, see Logical indexing):
b = [1, 2, 3, 4, 5] println(b[b .> 3]) # [4, 5] — элементы больше 3
In Julia, ranges can be set not only directly, but also using variables. For example:
arr = [10, 20, 30, 40, 50]
a = 1:2:5 # Задаем диапазон в переменной
println(arr[a]) # [10, 30, 50]
Logical indexing
Logical indexing in Julia allows you to select array elements based on the conditions that the logical array returns (true/false) of the same dimension as the original array. This method is useful for filtering data.
+ Example:
# Исходный массив
a = [10, 20, 30, 40, 50]
# Условие: выбрать элементы больше 25
filtered = a[a .> 25] # [30, 40, 50]
println(filtered)
# Condition: elements that are multiples of 10
filtered = a[a .% 10 .== 0] # [10, 20, 30, 40, 50]
println(filtered)
here:
-
operator
.before the condition (.>,.==) means an element-by-element operation. A more detailed description of such operations is provided in the article. Vectorisation and logical indexing. -
logical array
[false, false, true, true, true]it will be used to select the appropriate elements.
An example with a multidimensional array:
# Матрица 2x3
m = [1 2 3; 4 5 6]
# Условие: выбрать элементы больше 3
filtered = m[m .> 3] # [4, 5, 6]
println(filtered)
Operators for working with arrays, vectors, and matrices
Julia provides operators that simplify working with arrays, whether they are one—dimensional (vectors), two-dimensional (matrices), or more complex multidimensional structures. Here are the main operators that are used for indexing, transforming, and combining data.:
-
Operator
:It is used to select all the elements of an array along a certain dimension or to create ranges.Example:
# Исходный массив m = [1 2 3; 4 5 6; 7 8 9] # Все элементы первой строки println(m[1, :]) # [1, 2, 3] # Все элементы второго столбца println(m[:, 2]) # [2, 5, 8] # Диапазон индексов println(m[1:2, 1:2]) # [1 2; 4 5] -
Operator
'It is used for conjugation (transposition for real numbers). It only works with numeric arrays.Example:
# Вектор-строка v = [1 2 3] # Транспонирование в столбец println(v') # [1; 2; 3;;]For transposing arrays with complex numbers, the operator 'it also returns a complex conjugate result. If you only need to convert rows to columns (without conjugation), then use the functiontranspose.
|
To transpose arrays with non-numeric elements (for example, strings or custom types), use the function If you apply the operator
|
-
Operator
;It is used for combining arrays vertically, i.e. adding rows.Example:
# Исходные векторы a = [1, 2, 3] b = [4, 5, 6] # Вертикальная конкатенация result = [a; b] println(result) # 6-element Vector{Int64}:[1; 2; 3; 4; 5; 6]
Iterating over arrays using for
In Julia, arrays can be conveniently iterated through using a loop. for. Let’s look at the main ways to work with arrays via for. The following syntax is used to iterate through all the elements of the array:
arr = [10, 20, 30, 40]
for x in arr
println(x)
end
Output
10
20
30
40
Sometimes it is necessary to get not only the values, but also their indexes. To do this, use eachindex, which automatically selects the optimal indexing method:
arr = ["a", "b", "c"]
for i in eachindex(arr)
println("Элемент ", i, ": ", arr[i])
end
Output
Элемент 1: a
Элемент 2: b
Элемент 3: c
An alternative way to get the index and value is the function enumerate:
arr = ["apple", "banana", "cherry"]
for (i, val) in enumerate(arr)
println("$i: $val")
end
Output
1: apple
2: banana
3: cherry
Nested loops can be used for multidimensional arrays.:
matrix = [1 2 3; 4 5 6]
for i in 1:size(matrix, 1) # Проход по строкам
for j in 1:size(matrix, 2) # Проход по столбцам
println("matrix[$i, $j] = ", matrix[i, j])
end
end
Output
matrix[1, 1] = 1
matrix[1, 2] = 2
matrix[1, 3] = 3
matrix[2, 1] = 4
matrix[2, 2] = 5
matrix[2, 3] = 6
Instead of nested loops, you can use for directly:
matrix = [1 2 3; 4 5 6]
for x in matrix
println(x)
end
Output
1
4
2
5
3
6
Julia iterates through the elements in columns, not rows. To bypass the array by lines, you can use permutedims or eachrow:
for row in eachrow(matrix)
println(row)
end
Output
[1, 2, 3]
[4, 5, 6]