/\⌿⍀,⍪
Contents
/\⌿⍀,⍪
#
Replicate /
#
Next up is /
. When what’s on its left is an array rather than a function it instead acts like a function, which makes it unusual. We cover the operator case of /
elsewhere, e.g. +/
for sum.
As a function, /
is called replicate. It replicates each element on the right to as many copies as indicated by the corresponding element on the left:
1 1 2 1 2 1 2 1/'Misisipi'
Mississippi
A more common usage is with a Boolean left argument, where it then acts as a filter:
1 0 1 1 0 0 1 0 1 1 1/'Hello World'
HllWrld
It has one more trick: if you use a negative number, then it replaces the corresponding element with that many prototypes (spaces for characters and zeros for numbers):
1 1 ¯1 1 1/'Hello'
He lo
You can also use a single scalar to “empty” an array:
0/'abc'
1/'abc'
abc
1/x
can also be used to ensure that x
has at least one dimension (it ravels scalars, leaving all other arrays untouched):
⍴1/8 ⍝ Scalar becomes vector, rank 1
⍴1/8 8 ⍝ Higher ranks remain untouched
1
2
Expand \
#
/
has a cousin, \
, which, when used as a function, is called expand.
Positive numbers on the left also replicate like with /
but negative numbers insert that many prototypical elements at that position:
1 1 ¯1 1 1 1\1 2 3 4 5
1 2 0 3 4 5
You can use 0
instead of ¯1
which makes it convenient to use Boolean left arguments.
We can now begin to see how we can insert into an array. Let’s go back to the problem of inserting 3 in between 2 and 4 in the list 1 2 4 5. Our method was:
Get the indices of the elements:
⍳≢1 2 4 5
1 2 3 4
Look where the index is 2:
2=⍳≢1 2 4 5
0 1 0 0
That’s where we want to expand:
1+2=⍳≢1 2 4 5
1 2 1 1
Use \
to perform the expansion:
(1+2=⍳≢1 2 4 5)\1 2 4 5
1 2 2 4 5
Replace the extra 2 with our desired element:
3@(1+2)⊢(1+2=⍳≢1 2 4 5)\1 2 4 5
1 2 3 4 5
Just like the operators /
and \
each have a sibling, ⌿
and ⍀
which do the same thing but along the first axis (i.e. on the major cells) so to with the functions /
and \
:
(1 0 1/3 3⍴⎕A) (1 0 1⌿3 3⍴⎕A)
(1 ¯2 1 1\3 3⍴⎕A) (1 ¯2 1 1⍀3 3⍴⎕A)
┌──┬───┐ │AC│ABC│ │DF│GHI│ │GI│ │ └──┴───┘
┌─────┬───┐ │A BC│ABC│ │D EF│ │ │G HI│ │ │ │DEF│ │ │GHI│ └─────┴───┘
Ravel ,
#
Monadic ,
ravels. It takes all the scalars of an array and makes a single vector (list) out of them. This includes a scalar, so ,3
is a one-element vector:
3 3⍴⎕A
,3 3⍴⎕A
ABC DEF GHI
ABCDEFGHI
Question:
Isn’t that the same as monadic
∊
?
It is not. For example,
∊3 3⍴⎕A
∊3 3 3⍴⍳27
ABCDEFGHI
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
The difference is that ∊
will take all the data and make it a simple vector. ,
will take all the scalars and make it a (potentially nested) vector:
∊2 2⍴'abc' 'def' 'ghi' 'jkl'
,2 2⍴'abc' 'def' 'ghi' 'jkl'
abcdefghijkl
┌───┬───┬───┬───┐ │abc│def│ghi│jkl│ └───┴───┴───┴───┘
∊
is the same as recursive application of ⊃,/
.
Catenate ,
#
Which brings us to dyadic ,
, catenate, which is simply concatenation:
1 2 3,4 5 6
1 2 3 4 5 6
,
can also get specified an axis upon which to act:
(2 3⍴⎕A),[1](2 3⍴⍳6)
(2 3⍴⎕A),[2](2 3⍴⍳6)
A B C D E F 1 2 3 4 5 6
ABC 1 2 3 DEF 4 5 6
You can even use fractional axes to specify that you want to concatenate along a new inserted axis between the next lower and higher integer axes:
(2 3⍴⎕A),[0.5](2 3⍴⍳6) ⍝ 3D array
(2 3⍴⎕A),[1.5](2 3⍴⍳6) ⍝ 3D array
A B C D E F 1 2 3 4 5 6
A B C 1 2 3 D E F 4 5 6
This works for the monadic form too:
,[0.5]2 3⍴⎕A
⍴,[0.5]2 3⍴⎕A
,[1.5]2 3⍴⎕A
⍴,[1.5]2 3⍴⎕A
ABC DEF
1 2 3
ABC DEF
2 1 3
Catenate first ⍪
#
Then we have ⍪
. The dyadic ⍪
is a synonym for ,[1]
, and it’s sometimes referred to as catenate first:
(2 3⍴⎕A),[1](2 3⍴⍳6)
(2 3⍴⎕A)⍪(2 3⍴⍳6)
A B C D E F 1 2 3 4 5 6
A B C D E F 1 2 3 4 5 6
Table ⍪
#
Monadic ⍪
is called table as it ensures that the result is a table. It ravels the major cells of an array and makes each one of them into a row (i.e. a major cell) of a matrix:
2 3 4⍴⎕A
⍪2 3 4⍴⎕A
ABCD EFGH IJKL MNOP QRST UVWX
ABCDEFGHIJKL MNOPQRSTUVWX
That is, monadic ⍪
is just a synonym for ,⍤¯1
(except for scalars). To be universal, we’d need to say {,⍤¯1⊢1/⍵}
.