Замените элементы в массиве глаголом J `I.`

Вот простая замена списка ранга 1 с использованием глагола I.:

y=: _3 _2 _1 1 2 3
0 (I. y<0) } y

Результат

0 0 0 1 2 3

Как сделать такую ​​замену для матрицы ранга 2?

Например,

y2 =: 2 3 $ _3 _2 _1 1 2 3
0 (I. y2<0) } y2

Я получил (J806)

|index error
|   0    (I.y2<2)}y2

Причина, кажется,

(I. y2 < 0)

дает

0 1 2
0 0 0

что не очень хорошо воспринимается }.


j
person Zhe Hu    schedule 15.02.2019    source источник


Ответы (2)


Самый простой ответ на эту проблему — использовать диадический >. (Больший из) . ..

   0 >. y2
0 0 0
1 2 3

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

   (0 > y2)} y2 ,: 0
0 0 0
1 2 3

Если вы хотите использовать его как глагол, вы можете использовать форму герундия (v1`v2)} y ↔ (v1 y)} (v2 y):

   (0 > ])`(0 ,:~ ])} y2
0 0 0
1 2 3

Если ваш вопрос больше касается замены индекса рассеяния, то это тоже возможно. Вам нужно получить 2D-индексы позиций, которые вы хотите заменить, например:

   4 $. $. 0 > y2
0 0
0 1
0 2

Теперь упакуйте эти индексы и используйте диадический }:

   0 (<"1 (4 $. $. 0 > y2)) } y2
0 0 0
1 2 3

Опять же, вы можете превратить это в глагол, используя левый аргумент герундия для диадического } (x (v0`v1`v2)} y ↔ (x v0 y) (x v1 y)} (x v2 y)) следующим образом:

   0  [`([: (<"1) 4 $. [: $. 0 > ])`]} y2
0 0 0
1 2 3

Or

   100 101 102  [`([: (<"1) 4 $. [: $. 0 > ])`]} y2
100 101 102
  1   2   3

Чтобы немного привести это в порядок, вы можете определить getIdx как отдельный глагол...

   getIdx=: 4 $. $.
   0 [`([: <"1@getIdx 0 > ])`]} y2
0 0 0
1 2 3
person Tikkanz    schedule 17.02.2019
comment
Хорошие решения. Я постоянно забываю о разреженных индексах. Я вижу, что используется все чаще и чаще. - person bob; 18.02.2019
comment
@bob, использующий разреженные ($) операции для получения индексов, не самое очевидное решение, но, учитывая огромное улучшение производительности по сравнению с другими методами, это очень убедительно. - person Tikkanz; 18.02.2019
comment
это должно быть... разреженные ($.) операции... - person Tikkanz; 18.02.2019

Это не очень хорошее решение. Мой первоначальный подход состоял в том, чтобы изменить ранг теста, чтобы он смотрел на каждую строку отдельно, но в общем случае это не работает (см. комментарии ниже).

 [y2 =: 2 3 $ _3 _2 _1 1 2 3  
_3 _2 _1
 1  2  3


   I. y2<0
0 1 2
0 0 0


   0 (I. y2<0)"1 } y2  NB. Rank of 1 applies to each row of y2
0 0 0
1 2 3
person bob    schedule 15.02.2019
comment
Хорошая точка зрения. ($ $ 0&(([: I. 0 <~ ]) } )@:,) y2 будет работать, сглаживая массив, а затем снова создавая его, но тем временем давайте посмотрим, сможет ли кто-нибудь придумать лучший ответ. Лично я бы не стал использовать } для этого. Что-то вроде (* -.@:<&2) y2 больше похоже на J. - person bob; 16.02.2019