Двумерные (многомерные) массивы
Кроме того, что в конструкторе Array{Any,1}()
можно заменить единичку на другую цифру, для создания многомерных массивов можно можно использовать синтаксические конструкции, описанные ниже.
Я пытаюсь навести порядок в своей голове и запомнить этот путанный синтаксис. Так что, я вывел себе правила для запоминания. Придется немного вернуться к одноразмерным массивам.
- Одномерный массив (он же вектор) - это "вертикальный" массив.
Это имеет значение, т.к. обход всех элементов двумерного массива эффективен, когда он происходит сначала по внутренней (вертикальной) размерности, а потом по внешней (горизонтальной). Так они устроены. Второе. Если обращаться к двумерному массиву, как к простой коллекции, т.е. последовательно, то именно в таком порядке и будут получены элементы. Как мы увидим ниже, REPL отображает массивы, тоже, сначала - по вертикали.
- Элементы одномерного массива разделяются запятой.
Вот, как он выглядит:
julia> [1, 2]
2-element Array{Int64,1}:
1
2
- Второе измерение идет по горизонтали.
Это наращивание количества колонок. Оно будет внешним циклом последовательного обхода. Таким образом, массив 3x2 - это "три строки (ряда)" на "две колонки".
- Колонки разделяются пробелом.
Вырожденный случай двумерного массива, массив 1x3:
julia> [1 2 3]
1×3 Array{Int64,2}:
1 2 3
Итак, горизонтальная конкатенация:
julia> [[1,2,3] [4,5,6]]
3×2 Array{Int64,2}:
1 4
2 5
3 6
Вертикальная конкатенация.
Все становится сложнее, если пробел заменить переносом строки:
julia> [[1,2,3]
[4,5,6]]
6-element Array{Int64,1}:
1
2
3
4
5
6
Задумка авторов такова. Пусть, мы имеем два массива:
julia> a1=[1,2,3]
3-element Array{Int64,1}:
1
2
3
julia> a2=[3,4,5]
3-element Array{Int64,1}:
3
4
5
Тогда, оъединить их в двумерный можно так (горизонтально):
julia> [a1 a2]
3×2 Array{Int64,2}:
1 3
2 4
3 5
или так (вертикально), в данном случае - в одно измерение:
julia> [a1
a2]
6-element Array{Int64,1}:
1
2
3
3
4
5
Пусть, это будет правило:
- перенос строки добавляет новые строки (ряды)
Если же поставить между ними запятую (не важно, с переносом строки или без), то конкатенации не будет: мы получим одномерный массив массивов. Т.е. мы просто перечисляем элементы вектора, а их тип - вопрос второстепенный. Точно так же мы могли бы заполнить вектор любыми другими типами. Итак, еще одно правило:
- запятая говорит: "внутрь элементов не заглядываем":
julia> [a1, a2]
2-element Array{Array{Int64,1},1}:
[1,2,3]
[3,4,5]
Теперь красивый синтаксис "что на коробке - то и в коробке":
julia> [[1 2 3]
[3 4 5]]
2×3 Array{Int64,2}:
1 2 3
3 4 5
Проще:
julia> [1 2 3
3 4 5]
2×3 Array{Int64,2}:
1 2 3
3 4 5
С вышеперечисленными правилами не конфликтует.
А для случаев, когда нужно все это записать в одну строку -
- вместо переноса строки можно использовать точку с запятой:
julia> [[1 2 3]; [3 4 5]]
2×3 Array{Int64,2}:
1 2 3
3 4 5
Оно же:
julia> [1 2 3; 3 4 5]
2×3 Array{Int64,2}:
1 2 3
3 4 5
И, для закрепления, вырожденный случай:
julia> [1;2;3]
3-element Array{Int64,1}:
1
2
3
А чем это отличается от: [1,2,3]
? А тем, что точка с запятой заглядывает внутрь элементов, а запятая - нет.
Обратиться к одиночным элементам двумерного массива можно указывая индексы через запятую внутри квадратных скобок:
julia> a2x = [[2,3] [4,5]]
2×2 Array{Int64,2}:
2 4
3 5
julia> a2x[1,2]
4
Доступ к срезу массива таков:
julia> view(a2x,:,:)
2×2 SubArray{Int64,2,Array{Int64,2},Tuple{Colon,Colon},true}:
2 4
3 5
julia> view(a2x,:)
4-element SubArray{Int64,1,Array{Int64,1},Tuple{Colon},true}:
2
3
4
5
julia> view(a2x,1,:)
2-element SubArray{Int64,1,Array{Int64,2},Tuple{Int64,Colon},true}:
2
4
julia> view(a2x,:,2)
2-element SubArray{Int64,1,Array{Int64,2},Tuple{Colon,Int64},true}:
4
5
SubArray
ссылается на родительский массив без копирования его элементов.
К двумерному массиву можно обращаться последовательно, как к одномерному:
julia> a2x[3]
4
julia> for i in a2x println(i) end
2
3
4
5
Двумерный массив отличается от массива массивов, вот, для наглядности, массив массивов:
julia> aa = [[x, x*2] for x in 1:2]
2-element Array{Array{Int64,1},1}:
[1,2]
[2,4]
обращение к элементам здесь другое:
julia> aa[2][2]
4
Синтаксис горизонтальной, вертикальной и горизонтально-вертикальной конкатенации раскрывается в вызовы соответствующих функций hcat
, vcat
, hvcat
. Вместо использования квадраных скобок, можно пользоваться ими. Вы можете получить подробную справку по ним в REPL.