Vocabulary/Idioms

From J Wiki
Jump to: navigation, search

Back to: Vocabulary

Idioms

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