Как реализовать что-то похожее на необычное индексирование в Юлии? - PullRequest
0 голосов
/ 02 октября 2018

Я очень знаком с Джулией.Поэтому, пожалуйста, извините, если это глупая проблема.

У меня есть матрица 4 * 4 AA.

julia> AA
4×4 Array{Int64,2}:
  1   2   3   4
  5   6   7   8
  9  10  11  12
 13  14  15  16

У меня есть массив pv и pq, содержащийиндексирование информации.

julia> pv
3-element Array{Int64,1}:
 1
 3
 4

julia> pq
3-element Array{Int64,1}:
 2
 1
 4

Я хочу присвоить ноль элементам AA[1,2], AA[3,1] и AA[4,4].

Если я запускаю AA[pv,pq] = 0, тогда вывод:

4×4 Array{Int64,2}:
 0  0   3  0
 5  6   7  8
 0  0  11  0
 0  0  15  0 

Но мне нужно это как вывод

4×4 Array{Int64,2}:
  1   0   3   4
  5   6   7   8
  0  10  11  12
 13  14  15  0

Я знаю, это называется Fancy Indexing в Python.Но как я могу сделать это в Джулии?Я не могу запустить два оператора if с переменными, которые проверяют индекс строки и столбца.

Спасибо

Ответы [ 3 ]

0 голосов
/ 02 октября 2018

Другим вариантом будет использование CartesianIndex:

julia> AA[CartesianIndex.(pv, pq)]
3-element Array{Int64,1}:
  2
  9
 16

julia> AA[CartesianIndex.(pv, pq)] .= 0
3-element view(::Array{Int64,2}, CartesianIndex{2}[CartesianIndex(1, 2), CartesianIndex(3, 1), CartesianIndex(4, 4)]) with eltype Int64:
 0
 0
 0

julia> AA
4×4 Array{Int64,2}:
  1   0   3   4
  5   6   7   8
  0  10  11  12
 13  14  15   0

Обратите внимание, что вы должны использовать .= вместо =, иначе вы получите загадочную ошибку no method matching setindex_shape_check(::Int64, ::Int64) в 1,0 .. котораявыдает приятное предупреждение об устаревании в 0.7, что я, вероятно, все еще должен использовать.; -)

0 голосов
/ 03 октября 2018

Добавляя мои 2 ¢ для завершения,

Джулия поддерживает линейные индексы «столбцов-мажорных порядков», такие как matlab (хотя я отмечаю, что Julia 1.0 устарела как эквивалентные функции sub2ind и ind2sub matlab)).

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

На практике, в текущем состоянииЧто касается Джулии, это не сильно отличается от использования декартового индекса, но в некоторых случаях может быть предпочтительнее, например, если вы знаете, что будете использовать эти индексы для дальнейших операций или для читабельности / перехода от кода Matlab и т. д.

Например,

julia> A = copy( reshape( 10:10:160, (4,4) )' )
4×4 Array{Int64,2}:
  10   20   30   40
  50   60   70   80
  90  100  110  120
 130  140  150  160

julia> pv = [1,3,4];   pq = [2,1,4];

julia> A_linearIndices = LinearIndices(A)
4×4 LinearIndices{2,Tuple{Base.OneTo{Int64},Base.OneTo{Int64}}}:
 1  5   9  13
 2  6  10  14
 3  7  11  15
 4  8  12  16

julia> L = [ A_linearIndices[i...] for i in zip(pv, pq) ]
3-element Array{Int64,1}:
  5
  3
 16

julia> A[L]
3-element Array{Int64,1}:
  20
  90
 160

julia> A[L] .= 0; A
4×4 Array{Int64,2}:
  10    0   30   40
  50   60   70   80
   0  100  110  120
 130  140  150    0

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


РЕДАКТИРОВАТЬ : Код отредактирован для отображения назначения также с помощью линейного индекса.Обратите внимание, что я должен был сделать A правильным массивом, а не хранить его как объект «ReshapedArray», так как последний жалуется, если вы пытаетесь индексировать его напрямую.

0 голосов
/ 02 октября 2018

Один вариант:

julia> for el in zip(pv, pq)
           AA[el...] = 0
       end

julia> AA
4×4 Array{Int64,2}:
  1   0   3   4
  5   6   7   8
  0  10  11  12
 13  14  15   0
...