3

Here is a simple replace for a rank-1 list using the I. verb:

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

The result is

0 0 0 1 2 3

How do I do such a replacement for a rank-2 matrix?

For example,

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

I got (J806)

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

The reason seems to be

(I. y2 < 0)

gives

0 1 2
0 0 0

which isn't taken well by }.

2 Answers 2

4

The simplest answer for this problem is to use dyadic >. (Larger of) ...

   0 >. y2
0 0 0
1 2 3

If you want to use a more general conditional replacement criteria, then the following form may be useful:

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

If you want it as a verb then you can use the gerund form (v1`v2)} y ↔ (v1 y)} (v2 y) :

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

If your question is more about scatter index replacement then that is possible too. You need to get the 2D indices of positions you want to replace, for example:

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

Now box those indices and use dyadic }:

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

Again you can turn this into a verb using a gerund left argument to dyadic } (x (v0`v1`v2)} y ↔ (x v0 y) (x v1 y)} (x v2 y)) like this:

   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

To tidy this up a bit you could define getIdx as separate verb...

   getIdx=: 4 $. $.
   0 [`([: <"1@getIdx 0 > ])`]} y2
0 0 0
1 2 3
Sign up to request clarification or add additional context in comments.

3 Comments

Nice solutions. I keep forgetting about the sparse indices. I see that used more and more often.
@bob using sparse ($) operations to get indices is not the most obvious solution, but given the huge performance improvement over other methods, it is very compelling.
that should be "... sparse ($.) operations ..."
3

This is not a good solution. My original approach was to change the rank of the test so that it looks at each row separately, but that does not work in the general case (see comments below).

 [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

1 Comment

Good point. ($ $ 0&(([: I. 0 <~ ]) } )@:,) y2 would work by flattening the array and then building it back up again, but in the meantime let's see if anyone can come up with a better answer. I would personally not use } for this. Something like (* -.@:<&2) y2 feels more J like.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.