Search code examples
j

amend a subarray in place in j?


I've got two ways to amend a subarray in J but I don't like either of them.

(Imagine selecting a rectangle in a paint program and applying some arbitrary operation to that rectangle in place.)

  t =. i. 10 10         NB. table to modify
  xy=. 2 3 [ wh =. 3 2  NB. region i want want to modify
  u =. -@|.             NB. operation to perform on region

I can fetch the subarray and apply the operation in one step with cut (;.0):

  st =. ((,./xy),:(|,./wh)) u;.0 t

Putting it back is easy enough, but seems to require building a large boxed array of indices:

  (,st) (xy&+each,{;&:i./wh) } t

I also tried recursively splitting and glueing the table into four "window panes" at a time:

  split =: {. ; }.  NB. split y into 2 subarrays at index x
  panes =: {{ 2 2$ ; |:L:0 X split&|:&.> Y split y [ 'Y X'=.x }}
  glue =: [: ,&>/ ,.&.>/"1  NB. reassamble

  xy panes t
┌────────┬────────────────────┐
│ 0  1  2│ 3  4  5  6  7  8  9│
│10 11 12│13 14 15 16 17 18 19│
├────────┼────────────────────┤
│20 21 22│23 24 25 26 27 28 29│
│30 31 32│33 34 35 36 37 38 39│
│40 41 42│43 44 45 46 47 48 49│
│50 51 52│53 54 55 56 57 58 59│
│60 61 62│63 64 65 66 67 68 69│
│70 71 72│73 74 75 76 77 78 79│
│80 81 82│83 84 85 86 87 88 89│
│90 91 92│93 94 95 96 97 98 99│
└────────┴────────────────────┘

NB. then split the lower right pane again,
NB. extract *its* upper left pane...
s0 =.  1 1 {:: p0 =. xy panes t
s1 =. 0 0 {:: p1 =. wh panes s0

NB. apply the operation and reassemble:
p1a =. (<u s1) (<0 0) } p1
glue (<glue p1a) (<1 1) } p0

The first approach seems to be the quicker and easier option, but it feels like there ought to be a more primitive way to apply a verb at a sub-array without extracting it, or to paste in a subarray at some coordinates without manually creating the array of indices for each element.

Have I missed a better option?


Solution

  • I would begin by creating the set of indices that I wanted to amend

    [ ind =. < xy + each i. each wh
        ┌───────────┐
        │┌─────┬───┐│
        ││2 3 4│3 4││
        │└─────┴───┘│
        └───────────┘
    

    I can use those to select the atoms I want from t

       ind { t
    23 24
    33 34
    43 44
    

    And if I can select with them then I can use the same indices to amend t

       _ ind } t
     0  1  2  3  4  5  6  7  8  9
    10 11 12 13 14 15 16 17 18 19
    20 21 22  _  _ 25 26 27 28 29
    30 31 32  _  _ 35 36 37 38 39
    40 41 42  _  _ 45 46 47 48 49
    50 51 52 53 54 55 56 57 58 59
    60 61 62 63 64 65 66 67 68 69
    70 71 72 73 74 75 76 77 78 79
    80 81 82 83 84 85 86 87 88 89
    90 91 92 93 94 95 96 97 98 99
    

    and finally I can use a hook with the left tine being ind}~ after preprocessing t with the right tine (ind u@{ ]) to get my result

    (ind}~ ind u@{ ]) t
         0  1  2   3   4  5  6  7  8  9
        10 11 12  13  14 15 16 17 18 19
        20 21 22 _43 _44 25 26 27 28 29
        30 31 32 _33 _34 35 36 37 38 39
        40 41 42 _23 _24 45 46 47 48 49
        50 51 52  53  54 55 56 57 58 59
        60 61 62  63  64 65 66 67 68 69
        70 71 72  73  74 75 76 77 78 79
        80 81 82  83  84 85 86 87 88 89
        90 91 92  93  94 95 96 97 98 99
    

    You actually gave me the solution when you asked how you can 'amend' your array in place.