Преобразовать вложенный массив в новое измерение

Учитывая массив следующим образом:

A = Array{Array{Int}}(2,2)
A[1,1] = [1,2]
A[1,2] = [3,4]
A[2,1] = [5,6]
A[2,2] = [7,8]

Тогда у нас есть, что A — это массив 2×2 с элементами типа Array{Int}:

2×2 Array{Array{Int64,N} where N,2}:
 [1, 2]  [3, 4]
 [5, 6]  [7, 8]

Доступ к записям можно получить, например, A[1,2], но A[1,2,2] не будет работать, поскольку третье измерение отсутствует в A. Однако A[1,2][2] работает, поскольку A[1,2] возвращает массив длиной 2.

Тогда возникает вопрос, как лучше преобразовать A в 3-мерный массив B, чтобы B[i,j,k] ссылался на i, j-й массив и k-й элемент в этом массиве. Например. B[2,1,2] = 6.

Есть простой способ сделать это, используя 3 вложенных цикла и восстанавливая массив поэлементно, но я надеюсь, что есть более удобная конструкция. (Возможно, какое-то применение cat?)

cat(3,first.(A),last.(A)) также дает ту же матрицу. Если более двух элементов во внутренних векторах, getindex можно использовать для обобщения этой конструкции.   —  person Calavoow    schedule 10.11.2017

Я понял один способ: B = permutedims(reshape(collect(Iterators.flatten(A)), (2,2,2)), [3,2,1]), но он очень плохо читается, и я бы предпочел использовать генераторы из ответа @durand ниже. Обобщая ваш ответ: cat(3, map(idx -> getindex.(A, idx),(1:2))...) может быть нормальным (для подходящих диапазонов).   —  person Calavoow    schedule 10.11.2017

Выражения в вашем комментарии также можно записать: permutedims(reshape(vcat(A...),2,2,2),[2,3,1]) и cat(3,(getindex.(A,i) for i=1:2)...)   —  person Calavoow    schedule 10.11.2017

См. также:  Как управлять уведомлениями о событиях для отдельных участников, а не для всей команды?
Понравилась статья? Поделиться с друзьями:
IT Шеф
Комментарии: 3
  1. Calavoow

    Вы можете построить трехмерный массив из A, используя понимание массива

    julia> B = [ A[i,j][k] for i=1:2, j=:1:2, k=1:2 ]
    2×2×2 Array{Int64,3}:
    [:, :, 1] =
     1  3
     5  7
    
    [:, :, 2] =
     2  4
     6  8
    
    julia> B[2,1,2]
    6
    

    Однако более общим решением было бы перегрузить функцию getindex для массивов с тем же типом A. Это более эффективно, поскольку нет необходимости копировать исходные данные.

    julia> import Base.getindex
    
    julia> getindex(A::Array{Array{Int}}, i::Int, j::Int, k::Int) = A[i,j][k]
    getindex (generic function with 179 methods)
    
    julia> A[2,1,2]
    6
    
  2. Calavoow

    Благодаря комментариям Дэна Гетца, я считаю, что следующее работает хорошо и является лаконичным:

    cat(3,(getindex.(A,i) for i=1:2)...)
    

    где 2 — длина вложенного массива. Это также будет работать для более высоких измерений.

  3. Calavoow

    permutedims(reshape(collect(Base.Iterators.flatten(A)), (2,2,2)), (2,3,1))

    также выполняет свою работу и, кажется, быстрее, чем принятый cat() ответ для меня.

    РЕДАКТИРОВАТЬ: Извините, я только что увидел, что это уже было предложено в комментариях.

Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: