APL: array's element replacement and multiplication

646 views Asked by At

Let's say in APL language, I have a 2D array of shape 10x3. I cannot figure it out how to: replace all the occurrence of some specific numbers (e.g. 1, 2, 3, 4) in the entire array with 0, 10, 100, 1000 respectively. So I want to map 1 to 0, 2 to 10, 3 to 100 and 4 to 1000 in the entire array.

1

There are 1 answers

0
Adám On

I'll be using this example data:

      ⎕ ← array ← ? 10 3 ⍴ 10
 5  7  8
10  2 10
 9  8 10
 3  5  4
 6  6  4
 2  9  7
 4  5 10
 1  9  4
 1 10  1
10  5  3
      specific ← 1 2 3 4
      replacements ← 0 10 100 1000

Let's define a helper function to identify occurrences of elements that need to be mapped, namely those that are members of our list of specific numbers:

      Occurrences ← {⍵ ∊ specific}
      Occurrences array
0 0 0
0 1 0
0 0 0
1 0 1
0 0 1
1 0 0
1 0 0
1 0 1
1 0 1
0 0 1

Next, we define a mapping function that looks up the index of each element in the set of specific numbers, and uses those indices to index into the replacements:

      Map ← {replacements[specific ⍳ ⍵]}
      Map 3 1 4 1
100 0 1000 0

Now we can apply the mapping function at the occurrences:

      Map @ Occurrences array
   5  7    8
  10 10   10
   9  8   10
 100  5 1000
   6  6 1000
  10  9    7
1000  5   10
   0  9 1000
   0 10    0
  10  5  100

We can define the whole thing as a single replacement function:

      Replace ← Map @ Occurrences

Or even go directly for the full definition without the helper functions:

      Replace ← {replacements[specific ⍳ ⍵]} @ {⍵ ∊ specific}

The resulting definition will be the same: Try it online!

      Replace array
   5  7    8
  10 10   10
   9  8   10
 100  5 1000
   6  6 1000
  10  9    7
1000  5   10
   0  9 1000
   0 10    0
  10  5  100

We can even define a general-purpose replacement operator: Try it online!

      _Replace_ ← {⍺⍺ ( ⍵⍵ ⌷⍨∘⊂ ⍳ ) @ ( ∊∘⍺⍺ ) ⍵}
      (specific _Replace_ replacements) array
   5  7    8
  10 10   10
   9  8   10
 100  5 1000
   6  6 1000
  10  9    7
1000  5   10
   0  9 1000
   0 10    0
  10  5  100

This operator definition can be found in APLcart with a query like search and replace elements.


Consider using a mathematical relationship between the specific values and the replacement values, rather than doing a lookup:

      ( 1 ≠ specific ) × 10 * specific - 1
0 10 100 1000

Now we can write: Try it online!

      {( 1 ≠ ⍵ ) × 10 * ⍵ - 1} @ {⍵ ∊ specific} array
   5  7    8
  10 10   10
   9  8   10
 100  5 1000
   6  6 1000
  10  9    7
1000  5   10
   0  9 1000
   0 10    0
  10  5  100