# Vocabulary/Idioms

# Idioms

## Contents

Sometimes the right way to do a job in J isn't obvious. Here is a collection of useful tricks.

### Variable-Length Records

You need to split a list into fields where each field starts with a length.

First you calculate, for each position in `y`, where the *next* record would start **if** a record starts at that position.
The you use the special sequence `{~^:a:` to go through the chain of records.

data =. '5There2is1a4tide2in3the7affairs2of3men' NB. 1-byte numeric length betwenen words ]l =. >: (a. i. data) - a. i. '0' NB. Each start-of-record has a length. Others immaterial 6 37 57 54 67 54 3 58 68 2 50 5 69 58 53 54 3 ... ]n =. (#l) <. l + i. # l NB. Now each position of n has a next-record position 6 38 38 38 38 38 9 38 38 11 ... ]pos =. (n,_1) {~^:a: 0 NB. find all the record starting positions, and return them as an array 0 6 9 11 16 19 23 31 34 38 _1 ((i. #data) e. pos) <;._1 data NB. Extract the valid fields into boxes +-----+--+-+----+--+---+-------+--+---+ |There|is|a|tide|in|the|affairs|of|men| +-----+--+-+----+--+---+-------+--+---+

### Extract The Diagonal Of A Table

To extract the diagonal of a table, use `(<0 1) |: y`

]a =: 4 4 $ 'abcdefghijklmnop' abcd efgh ijkl mnop (<0 1) |: a NB. The main diagonal afkp (<0 1) |: i. 4 5 NB. For non-square arrays, it's the diagonal starting at the top-left 0 6 12 18

The method generalizes to higher-dimensional arrays. The `x` argument to `x |: y` specifies the axes to retain, with each box corresponding to one result axis, and with multiple axes in a box run together to make a single axis taken along a diagonal.

### Polynomial Multiplication

pmul =: +//.@(*/) 1 2 pmul 3 4 2 NB. (1+2x)(3+4x+2x^2)=3+10x+10x^2+4x^3 3 10 10 4

### Ordinal Number

The ** ordinal number** of an item of an array is the index the item would have if the array were sorted. The first item is ordinal 0, etc. Applying

`/: /: y`calculates the ordinal numbers.

/: /: 3 1 4 1 5 9 2 0 3 1 4 5

Ordinal numbers can be used to *unsort* an array, i.e. put a sorted array back into its original order. For example, suppose we want to modify a vector of integers so that duplicate values differ slightly from each other.

nn=. 3 1 4 1 5 9 2 6 5 3 5 8 9 7 9 /:~nn NB. Sort 1 1 2 3 3 4 5 5 5 6 7 8 9 9 9 </.~/:~nn NB. Box unique values +---+-+---+-+-----+-+-+-+-----+ |1 1|2|3 3|4|5 5 5|6|7|8|9 9 9| +---+-+---+-+-----+-+-+-+-----+

Now, add a small amount to each duplicate:

0.01 (] + [ * [: i. [: # ]) &.> </.~/:~nn +------+-+------+-+-----------+-+-+-+-----------+ |1 1.01|2|3 3.01|4|5 5.01 5.02|6|7|8|9 9.01 9.02| +------+-+------+-+-----------+-+-+-+-----------+ ;0.01(] + [ * [: i. [: # ])&.></.~/:~nn NB. Raze to remove boxes 1 1.01 2 3 3.01 4 5 5.01 5.02 6 7 8 9 9.01 9.02

Finally, use ordinal numbers to put the modified numbers back into their original order.

(/:/:nn) { ; 0.01 (] + [ * [: i. [: # ]) &.> </.~/:~nn 3 1 4 1.01 5 9 2 6 5.01 3.01 5.02 8 9.01 7 9.02

The final result tags each duplicate item by 0.01 times the number of duplicates preceding it.

### String Searching

**Forms For String Searches****Action****Preferred Form**Find Matching Positions `x I.@:E. y`Count Matching Positions `x +/@:E. y`Is Substring `x`in`y`?`x +./@:E. y`

str=. 'How now brown cow?' 'ow' I.@:E. str NB. Starting positions of 'ow' 1 5 10 15 'ow' +/@:E. str NB. Number of occurrences of 'ow' 4 'how' +./@:E. str NB. Is 'how' in string? 0 'How' +./@:E. str NB. Is 'How' in string? 1