Merge Vectors In APL

68 Views Asked by At

Using Dyalog APL I would like to take a Mask Vector where '-' means use the original character and any other character is to replace that position in the Data Vector. So in the example below, Mask 'a' is used on Vector 'b' to create Vector 'c'.

┌──────┬────────┬────┐
│X--Y-Z│--34--91│-+-+│ Mask Vector a
└──────┴────────┴────┘
┌──────┬────────┬────┐
│abcdef│hijklmno│stuv│ Data Vector b
└──────┴────────┴────┘
┌──────┬────────┬────┐
│XbcYeZ│hi34lm91│s+u+│ Resultant Vector c
└──────┴────────┴────┘

The vectors contain strings of different lengths. I do not wish to use any Regular Expression or Search and Replace function built into APL.

I created code to perform this function, but it seems far too complicated as it is creating matrices, rotating characters around, and pulling data out of rows. I am sure there is an easier way to perform this function in APL. I am interested in seeing what more experienced APL developers come up with.

2

There are 2 best solutions below

1
Essie Rivers On
mask  ← 'X--Y-Z' '--34--91' '-+-+'
data  ← 'abcdef' 'hijklmno' 'stuv'
where ← '-'≠mask
fill ← where/¨mask
(where/¨data) ← fill
data

The principal operation is (where/¨data) ← fill, which is an example of "selective assignment".

This operation can be more succinctly defined as an operator:

merge ← {d←⍵ ⋄ (w/¨d)←(w←⍺⍺≠⍺)/¨⍺ ⋄ d}

And called in the form mask ('-' merge) data

1
Adám On

In general, a great way to modify data in-place is th use the At operator @. It can be used in a couple of different ways, but here, we'll use the pattern substitution_data @ masking_function original_data:

      mask ← 'X--Y-Z' '--34--91' '-+-+'
      data ← 'abcdef' 'hijklmno' 'stuv'
      mask {(⍺~'-')@(⍺≠'-'⍨)⍵}¨ data
┌──────┬────────┬────┐
│XbcYeZ│hi34lm91│s+u+│
└──────┴────────┴────┘

Try it on TryAPL!

We use an outer loop { to process Each corresponding pair of elements from the mask and the data. Inside the dfn {}, the mask is and the data is .

The substitution data consists of all the characters in except dashes, so we remove the dashes with the Without function ~.

The masking function is actually applied to by the @ operator, but it ignores its argument by way of the constant operator which then just returns the dash character. The single dash is compared to the current to get a mask indicating which elements to modify.