⍳⍸∊⍷∪≠∩~#

Index generator #

Monadic is the index generator. ⍳a generates an array of shape a where the elements are the indices for that element:

10
2 4
1 2 3 4 5 6 7 8 9 10
┌───┬───┬───┬───┐
│1 1│1 2│1 3│1 4│
├───┼───┼───┼───┤
│2 1│2 2│2 3│2 4│
└───┴───┴───┴───┘

Any bets on what ⍳0 gives?

]display 0
┌⊖┐
│0│
└~┘

The empty numeric list. What about ⍳0 0?

]display 0 0
┌⊖──────┐
⌽ ┌→──┐ │
│ │0 0│ │
│ └~──┘ │
└∊──────┘

This is the same as 0 0⍴⍬; a 0x0 empty numeric matrix.

Index-of #

The dyadic version A⍳B is index-of. It finds the first occurrence of the major cells of B in the major cells of A:

'hello''l'
'hello''lo' 
3
3 5

If a cell is not a member, it will return a number one higher than the number of elements:

'hello''x'
6
(3 2'abcdef')(2 2'cdxy')
2 4

So the “cd” row is the second one, and the “xy” row is not there. This behaviour for elements that are not there is really useful for supplying a “default”:

'First' 'Second' 'Third' 'Missing'['abc''cdab']
┌─────┬───────┬─────┬──────┐
│Third│Missing│First│Second│
└─────┴───────┴─────┴──────┘

Where #

Monadic is where. It just takes a simple array and returns the list of non-zero indices.

0 1 0 1 1 
2 4 5
m2 30 1 0 1 1 0
m
0 1 0
1 1 0
┌───┬───┬───┐
│1 2│2 1│2 2│
└───┴───┴───┘

If the argument array is not Boolean, the values are taken to mean the repeat count for each index:

2 30 2 0 2 2 0
┌───┬───┬───┬───┬───┬───┐
│1 2│1 2│2 1│2 1│2 2│2 2│
└───┴───┴───┴───┴───┴───┘

A code golf trick: sum a Boolean array with ≢⍸ instead of +/,

≢⍸2 30 1 0 1 1 0
3

Interval index #

Dyadic is interval index. It takes a list of sorted arrays on the left, and for each array on the right, tells which “gap” (interval) it belongs.

1 10 100 10000 500 2000 3 10
0 3 4 1 2

So 0 is in interval number 0 (that is, before 1–10). 500 is in interval 3, which is 100–1000, etc. And as you can see from 10, it is in interval 2; 10–100. So intervals are [min,max). For higher rank arrays, it works like grade, i.e. on major cells.

Membership #

Dyadic is membership. For each scalar in the left argument, return a Boolean if it is a member of the right argument:

'aeiou''Hello World'
0 1 0 1 0

Question:

Does APL have an “insert at index” command? As in, given an array, an index and a value, insert value at the index in the array. Example: [1, 2, 4, 5], 2, 3 => [1, 2, 3, 4, 5]

There are a couple of approaches:

(⊂,3)@21 2 4 5
1 2 3 4 5

This appended a 3 to the 2, then flattened. You flatten with monadic which is the function we’re up to. A more traditional and better performing approach would be:

{3@(1+2)\⍨1+2=⍳≢}1 2 4 5
1 2 3 4 5

but we have not covered the \ function yet.

Enlist #

is enlist:

m(3)(2 2⍴⍳4)
m
┌─────┬───┐
│1 2 3│1 2│
│     │3 4│
└─────┴───┘
1 2 3 1 2 3 4

Find #

Next up is which is (as of yet) only dyadic. is find. It returns a Boolean array of the right argument’s shape with a 1 at the “top left” corner of occurrences of the left argument in the right argument:

'ss''Mississippi'
0 0 1 0 0 1 0 0 0 0 0

The ones here indicate the left “s” wherever “ss” begins. It also works for overlaps,

'aba''alababa'
0 0 1 0 1 0 0

and for higher-rank arrays:

2 20 1 0
3 30 1 1 0
(2 20 1 0)(3 30 1 1 0)
0 1
0 0
0 1 1
0 0 1
1 0 0
1 0 0
0 1 0
0 0 0

and also for nested arrays, too:

'aa' 'bbb''c' 'aa' 'bbb' 'dddd' 'aa' 'aa' 'bbb'
0 1 0 0 0 1 0

Quiz using : Determine if A is a prefix of B.

Click for quiz answer⊃⍷

How about: Is A a suffix of B?

Click for quiz answer{⊃(⊖⍺)⍷⊖⍵}

Union #

Next function is dyadic . It is basically union of multi-sets. However, it is symmetrical in a way you can often use to your advantage:

'abcc''cda'
'cda''abcc'
abccd
cdab

It preserves duplicates from the left argument, while only adding the items from the right necessary to make the result contain all elements from both. It will add duplicate elements from the right if they are not in the left, though:

'abcc''cdda'
abccdd

Unique #

The monadic is unique. It simply removes duplicates:

'mississippi'
misp

Unique mask #

Monadic is unique mask. It returns a Boolean vector which, when used as left argument to and with the original argument as right argument, returns the same as would on the original argument:

'mississippi'
'mississippi'
{()}'mississippi'
misp
1 1 1 0 0 0 0 0 1 0 0
misp

We’ll cover this in greater depth in a later chapter.

Intersection #

Dyadic is, of course, intersection, again asymmetric:

'abcc''cda'
'cda''abcc'
acc
ca

It removes elements from the left which are not present in the right. Duplicates in the right do not matter.

Without ~#

The last multi-set function is dyadic ~ which is without or except. It simply removes from the left whatever is on the right. Note that it can take even high-rank right arguments.

'Mississippi'~'pss'
Miiii

NOT ~#

Monadic ~ is logical NOT, simply swapping 1→0 and 0→1:

(3 30 1 1 0) (~3 30 1 1 0)
┌─────┬─────┐
│0 1 1│1 0 0│
│0 0 1│1 1 0│
│1 0 0│0 1 1│
└─────┴─────┘