Массивы Julia

Массив — это коллекция элементов одного типа данных, расположенных в определённом порядке; он может быть одномерным или многомерным массивом.

Julia поддерживает структуры данных массивов, которые могут хранить упорядоченную коллекцию, размер которой не фиксирован, а элементы могут быть одного или разных типов.

Массивы Julia — это изменяемые типизированные коллекции, используемые для списков, векторов, таблиц и матриц.

Индексные ключи массивов Julia могут быть представлены целыми числами, а размер массива не фиксирован.

Julia предоставляет множество функций, помогающих нам работать с массивами, таких как добавление элементов в массивы, объединение массивов и т. д.

Массивы Julia используют квадратные скобки[...]для указания, а несколько элементов используют запятые,для их разделения.

Синтаксис создания одномерного массива (то есть вектора):

[A, B, C, ...]

Создание одномерных массивов

Следующий пример создаёт простой одномерный массив:

Пример

julia> arr = [1,2,3]
3-элементный Vector{Int64}:
 1
 2
 3

В приведенном выше примере мы создали одномерный массив, содержащий 3 элемента, каждый элемент — 64-битное целое число, и этот одномерный массив привязан к переменнойarr.

Типы элементов массива также могут быть разными:

Пример

julia> arr =[1, "EXAMPLE", 2.5, pi]
4-элементный Vector{Any}:
 1
  "EXAMPLE"
 2.5
 π = 3.1415926535897...

В приведенном выше примере мы создали одномерный массив, содержащий 4 элемента разных типов.pi— это константаπ, каждый элемент — 64-битное целое число, и этот одномерный массив привязан к переменнойarr.

Конечно, можно также принудительно задать тип:

Пример

julia> arr = Int64[1,2,3]
3-элементный Vector{Int64}:
 1
 2
 3
julia> arr2 = String["Taobao","EXAMPLE","GOOGLE"]
3-элементный Vector{String}:
 "Taobao"
 "EXAMPLE"
 "GOOGLE"

Массив в примере вышеarrограничен только целыми числами,arr2ограничен только строками.

Мы также можем создать пустой массив:

Пример

julia> arr = Int64[]
Int64[]

julia> arr2 = String[]
String[]

К созданному массиву можно обращаться напрямую по значениям индексов. Первое значение имеет индекс 1 (не 0), второе — индекс 2, и так далее. Для последнего можно использоватьend, чтобы обозначить:

Пример

julia> arr = Int64[1,2,3]
3-элементный Vector{Int64}:
 1
 2
 3

julia> arr[2]
2
julia> arr2 = String["Taobao","EXAMPLE","GOOGLE"]
3-элементный Vector{String}:
 "Taobao"
 "EXAMPLE"
 "GOOGLE"

julia> arr2[1]
"Taobao"

julia> arr2[end]
"GOOGLE"

Указание типов и размерностей массива

Мы также можем использовать следующий синтаксис, чтобы указать тип и размерности массива:

Array{type}(undef, dims...)

undefозначает, что массив не инициализирован.

dims...может быть одним или несколькими кортежами размерностей, либо набором значений, когда размерности передаются как переменные аргументы.

dims...Число обозначает количество элементов; при нескольких размерностях используйте запятые,для их разделения.

Пример

julia> array = Array{Int64}(undef, 3)    # представляет одномерный массив с 3 элементами
3-элементный Vector{Int64}:
 4834342704
 4377305096
          0

julia> array = Array{Int64}(undef, 3, 3, 3)    # представляет трёхмерный массив, с 3 элементами в каждом измерении
3×3×3 Array{Int64, 3}:
[:, :, 1] =
 4562265712  0  0
          1  0  0
          0  0  0

[:, :, 2] =
 0  0  0
 0  0  0
 0  0  0

[:, :, 3] =
 0  0  0
 0  0  0
 0  0  0

В приведённом выше примере мы помещаем тип массива в фигурные скобки{}, undef используется, чтобы задать массив как неинициализированный и не имеющий никакого известного значения; поэтому в выводе мы получаем случайные числа.


Создание двумерных массивов и матриц

Мы можем опустить запятые между элементами массива,или использовать два двоеточия;;, таким образом мы можем создать двумерный массив, как в следующем примере:

Пример

julia> [1 2 3 4]
1×4 Matrix{Int64}:
 1  2  3  4
julia> [1;; 2;; 3;; 4]
1×4 Matrix{Int64}:
 1  2  3  4

Примечание:Вывод в первой строке1×4 Matrix{Int64}:, 1x4 обозначает матрицу с одной строкой и четырьмя столбцами.

Хотя в нём только одна строка, это всё ещё двумерный массив, потому что Julia распознаёт только векторы-столбцы, а не так называемые векторы-строки.

Чтобы добавить ещё одну строку, просто добавьте точку с запятой;, см. следующий пример:

Пример

julia> [1 2; 3 4]
2×2 Matrix{Int64}:
 1  2
 3  4

Вы также можете использовать двоеточия:и пробелы для этого, см. следующий пример:

Пример

julia> [1:2  3:4]
2×2 Matrix{Int64}:
 1  3
 2  4

Примечание:Вывод в первой строке2×2 Matrix{Int64}:, 2×2 обозначает матрицу с двумя строками и двумя столбцами.

Мы также можем встроить одномерные массивы одинаковой длины в квадратные скобки[]и разделить их пробелами, чтобы создать двумерный массив:

Пример

julia> [[1,2] [3,4] [5,6]]
2×3 Matrix{Int64}:
 1  3  5
 2  4  6

2x3представляет массив с двумя строками и тремя столбцами.

Ниже мы гибко используем точки с запятой;и пробелы , чтобы создать двумерный массив с двумя строками и тремя столбцами, а также массив с тремя строками и двумя столбцами:

Пример

julia> [[1;2] [3;4] [5;6]]
2×3 Matrix{Int64}:
 1  3  5
 2  4  6

julia> [[1 2]; [3 4]; [5 6]]
3×2 Matrix{Int64}:
 1  2
 3  4
 5  6

Использование функций диапазона для создания массивов

Многоточие ...

Вы можете использовать многоточие...для создания массива, как в следующем примере:

Пример

julia> [0:10...]
11-элементный Vector{Int64}:
  0
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10

Функция collect()

Синтаксис функции collect() выглядит следующим образом:

collect(start:step:stop)

start — начальное значение, step — размер шага, stop — конечное значение.

Эта функция возвращает массив.

В следующем примере значение равно 1, шаг равен 2, а конечное значение — 13:

Пример

julia> collect(1:2:13)
7-элементный Vector{Int64}:
  1
  3
  5
  7
  9
 11
 13

Функция collect() также может указывать тип, со следующим синтаксисом:

collect(element_type, start:step:stop)

В следующем примере создаётся массив чисел с плавающей запятой:

Пример

julia> collect(Float64, 1:2:5)
3-элементный Vector{Float64}:
 1.0
 3.0
 5.0

Функция range()

Функция range() может создавать диапазон и задавать размер шага, что удобно для вызова функцией collect().

Синтаксис функции range() выглядит следующим образом:

range(start, stop, length) range(start, stop; length, step) range(start; length, stop, step) range(;start, length, stop, step)

start — начальное значение, step — размер шага, stop — конечное значение, а length — длина.

Пример

julia> range(1, length=100)
1:100

julia> range(1, stop=100)
1:100

julia> range(1, step=5, length=100)
1:5:496

julia> range(1, step=5, stop=100)
1:5:96

julia> range(1, 10, length=101)
1.0:0.09:10.0

julia> range(1, 100, step=5)
1:5:96

julia> range(stop=10, length=5)
6:10

julia> range(stop=10, step=1, length=5)
6:1:10

julia> range(start=1, step=1, stop=10)
1:1:10

Если length не указан, иstop - startне является целым кратным step, то будет сгенерирован диапазон, заканчивающийся перед stop.

julia> range(1, 3.5, step=2)
1.0:2.0:3.0

Создание массивов с помощью range() и collect():

Пример

julia> collect(range(1,stop=10))
10-элементный Vector{Int64}:
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
julia> collect(range(1, length=15, stop=150))
15-элементный Vector{Float64}:
   1.0
  11.642857142857142
  22.285714285714285
  32.92857142857143
  43.57142857142857
  54.214285714285715
  64.85714285714286
  75.5
  86.14285714285714
  96.78571428571429
 107.42857142857143
 118.07142857142857
 128.71428571428572
 139.35714285714286
 150.0

Создание массивов с помощью включений и генераторов

Ещё один полезный способ создавать массивы — использовать включения.

Синтаксис включений для массивов выглядит так:

A = [ F(x,y,...) for x=rx, y=ry, ... ]

F(x,y,...) вычисляется для каждого значения переменных x, y и т. д. в заданных списках. Значения можно задавать любым итерируемым объектом, но обычно это диапазоны вроде 1:n или 2:(n-1), либо явные значения массива вроде [1.2, 3.4, 5.7]. Результатом является N-мерный плотный массив, размерности которого получаются конкатенацией размерностей диапазонов переменных rx, ry и т. д., а каждое вычисление F(x,y,...) возвращает скаляр.

Пример

julia> [n^2 for n in 1:10]
10-элементный Vector{Int64}:
   1
   4
   9
  16
  25
  36
  49
  64
  81
 100

Создание двумерного массива:

Пример

julia> [n*m for n in 1:10, m in 1:10]
10×10 Matrix{Int64}:
  1   2   3   4   5   6   7   8   9   10
  2   4   6   8  10  12  14  16  18   20
  3   6   9  12  15  18  21  24  27   30
  4   8  12  16  20  24  28  32  36   40
  5  10  15  20  25  30  35  40  45   50
  6  12  18  24  30  36  42  48  54   60
  7  14  21  28  35  42  49  56  63   70
  8  16  24  32  40  48  56  64  72   80
  9  18  27  36  45  54  63  72  81   90
 10  20  30  40  50  60  70  80  90  100

Включения также можно записывать без квадратных скобок, создавая объект, называемый генератором.

В следующем примере создаётся массив:

Пример

julia> collect(n^2 for n in 1:5)
5-элементный Vector{Int64}:
  1
  4
  9
 16
 25

Следующее выражение суммирует последовательность без выделения памяти:

Пример

julia> sum(1/n^2 for n=1:1000)
1.6439345666815615

Основные функции массивов Julia

Функция Описание
eltype(A) Aтип элементов в
length(A) Aколичество элементов в
ndims(A) Aразмерность
size(A) кортеж, содержащийAкортеж с количеством элементов в каждом измерении
size(A,n) AНет.nколичество элементов в измерении
axes(A) кортеж, содержащийAкортеж допустимых индексов
axes(A,n) Нет.nдиапазон допустимых индексов для измерения
eachindex(A) эффективный итератор для доступа кAкаждой позиции в
stride(A,k) наkшаг по измерению (расстояние в линейном индексе между соседними)
strides(A) содержащий шаг по каждому измерению

Создание и инициализация в Julia

Julia предоставляет множество функций для создания и инициализации массивов. В следующих функциях аргумент dims ... может быть кортежем, представляющим размерности, или переменным числом целочисленных значений в качестве размерностей. Первый аргумент большинства функций представляет тип элементов T массива. Если тип T опущен, по умолчанию используется Float64.

Функция Описание
Array{T}(undef, dims...) Плотный массив, который не инициализированArray
zeros(T, dims...) Массив, заполненный нулямиArray
ones(T, dims...) Массив, все элементы которого равны 1Array
trues(dims...) Массив, каждый элемент которого равенtrueизBitArray
falses(dims...) Массив, каждый элемент которого равенfalseизBitArray
reshape(A, dims...) Массив, содержащий те жеAмассив с теми же данными, но другими размерностями
copy(A) copyA
deepcopy(A) глубокая копия, т.е. копированиеA, и рекурсивное копирование его элементов
similar(A, T, dims...) Массив с таким жеAнеинициализированный массив того же типа (здесь имеются в виду dense, sparse и т. д.), но с указанным типом элементов и размерностями. Второй и третий параметры необязательны; если их опустить, по умолчанию используются тип элементов иAразмерности.
reinterpret(T, A) иAМассив с теми же двоичными данными, но тип элементов —T
rand(T, dims...) СлучайныйArray, значения элементов [ 0 , 1 ) [0, 1) равномерно распределены в полуоткрытом интервале и подчиняются независимому и одинаковому распределению первого порядка[1]
randn(T, dims...) СлучайныйArray, элементы имеют стандартное нормальное распределение, независимы и одинаково распределены
Matrix{T}(I, m, n) mlinenединичная матрица со столбцами (сначала нужно выполнитьusing LinearAlgebraчтобы использоватьI)
range(start, stop=stop, length=n) fromstartвstopwithnдиапазон линейно распределённых элементов
fill!(A, x) Со значениемxзаполнить массивA
fill(x, dims...) Массив, заполненныйxзаполненныйArray

zeros()Создает экземпляр массива, начальные значения всех элементов равны 0:

Пример

julia> zeros(Int8, 2, 3)
2×3 Matrix{Int8}:
 0  0  0
 0  0  0

julia> zeros(Int8, (2, 3))
2×3 Matrix{Int8}:
 0  0  0
 0  0  0

julia> zeros((2, 3))
2×3 Matrix{Float64}:
 0.0  0.0  0.0
 0.0  0.0  0.0
Другие расширения