From 4b3d058e7530787ad9e4eeb5de1b0e57418fbdf7 Mon Sep 17 00:00:00 2001 From: Bart Jablonski Date: Thu, 21 Sep 2023 21:19:44 +0200 Subject: [PATCH] The macroArray package [ver. 1.1.1] The macroArray package [ver. 1.1.1] Changes: - bug fixes. - code optimization. The SHA256 hash digest for package `macroArray`: `F*E9C0C58FB36AC40C76A518066B8C6F9942202A9DB2C2D737E95D2BB6E4ECED50` --- README.md | 2 +- hist/1.1.1/macroarray.md | 2204 +++++++++++++++++++++++++++++++++++++ hist/1.1.1/macroarray.zip | Bin 0 -> 52051 bytes macroarray.md | 6 +- macroarray.zip | Bin 51814 -> 52051 bytes 5 files changed, 2208 insertions(+), 4 deletions(-) create mode 100644 hist/1.1.1/macroarray.md create mode 100644 hist/1.1.1/macroarray.zip diff --git a/README.md b/README.md index bd85c83..6df0b91 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ The **macroArray** package implements an array, a hash table, and a dictionary c ); ``` -SHA256 digest for the latest version of `macroArray`: F*6A22A01868F4203862B3685F543D723C7DB8E9AB3C1A6357D2BFA030971B0D3C +SHA256 digest for the latest version of `macroArray`: F*E9C0C58FB36AC40C76A518066B8C6F9942202A9DB2C2D737E95D2BB6E4ECED50 [**Documentation for macroArray**](./macroarray.md "Documentation for macroArray") diff --git a/hist/1.1.1/macroarray.md b/hist/1.1.1/macroarray.md new file mode 100644 index 0000000..ca8b22d --- /dev/null +++ b/hist/1.1.1/macroarray.md @@ -0,0 +1,2204 @@ +- [The macroArray package](#macroarray) +- [Content description](#content-description) + * [`%appendArray()` macro](#appendarray-macro) + * [`%appendCell()` macro](#appendcell-macro) + * [`%array()` macro](#array-macro) + * [`%concatArrays()` macro](#concatarrays-macro) + * [`%deleteMacArray()` macro](#deletemacarray-macro) + * [`%do_over()` macro](#do-over-macro) + * [`%do_over2()` macro](#do-over2-macro) + * [`%do_over3()` macro](#do-over3-macro) + * [`%make_do_over()` macro](#make-do-over-macro) + * [`%mcHashTable()` macro](#mchashtable-macro) + * [`%mcDictionary()` macro](#mcdictionary-macro) + * [`%QzipArrays()` macro](#qziparrays-macro) + * [`%zipArrays()` macro](#ziparrays-macro) + * [`%sortMacroArray()` macro](#sortmacroarray-macro) + + * [License](#license) + +--- + +# The macroArray package [ver. 1.1.1] ############################################### + +The **macroArray** package implements a macro array facility: +- `%array()`, +- `%do_over()`, +- `%make_do_over()`, +- `%deletemacarray()`, +- `%concatarrays()`, +- `%appendcell()`, +- `%mcHashTable()`, +- `%zipArrays()`, +- `%sortMacroArray()`, +- `%mcDictionary()`, +- etc. + +The set of macros, which emulates classic +data-step-array functionality on the macro +programming level, is provided. + +*Note:* +If you are working with BIG macroarrays do not +forget to verify your session setting for macro +memory limits. Run: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + proc options group = macro; + run; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +to verify the following options: + +| option | description | +|-------------:|:-----------------------------------------------------------------------------------------------| +|`MEXECSIZE=` | specifies the maximum macro size that can be executed in memory. | +|`MSYMTABMAX=` | specifies the maximum amount of memory available to the macro variable symbol table or tables. | +|`MVARSIZE=` | specifies the maximum size for a macro variable that is stored in memory. | + +--- + +Package contains: + 1. macro appendarray + 2. macro appendcell + 3. macro array + 4. macro concatarrays + 5. macro deletemacarray + 6. macro do_over + 7. macro do_over2 + 8. macro do_over3 + 9. macro make_do_over + 10. macro mcdictionary + 11. macro mchashtable + 12. macro qziparrays + 13. macro sortmacroarray + 14. macro ziparrays + +Required SAS Components: + *Base SAS Software* + +*SAS package generated by generatePackage, version 20230904* + +The SHA256 hash digest for package macroArray: +`F*E9C0C58FB36AC40C76A518066B8C6F9942202A9DB2C2D737E95D2BB6E4ECED50` + +--- +# Content description ############################################################################################ + +## >>> `%appendArray()` macro: <<< ############ + +The `%appendArray()` macro is a macrowrapper +which allows to concatenate two macroarrays +created by `%array()` macro. + +By default values of the second macroarray are *not* removed. + +Dimensions of the first macroarray are extended. + +The `%appendArray()` macro executes like a pure macro code. + +### SYNTAX: ##################################################################### + +The basic syntax is the following, the `<...>` means optional parameters: +~~~~~~~~~~~~~~~~~~~~~~~sas +%appendArray( + first + ,second +) +~~~~~~~~~~~~~~~~~~~~~~~ + +**Arguments description**: + +1. `first` - *Required*, a name of a macroarray created by the `%array()` macro. + +2. `second` - *Required*, a name of a macroarray created by the `%array()` macro. + + + + +### EXAMPLES AND USECASES: ###################################################### + +**EXAMPLE 1.** Append macroarrays LL and MM. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(ll[2:4] $ 12, + function = quote(put(today() + 10*_I_, yymmdd10.)), + macarray=Y + ) + %array(mm[10:13] $ 1200, + function = quote(repeat("A",12*_I_)), + macarray=Y + ) + %put *%ll(2)*%ll(3)*%ll(4)*; + + %appendArray(ll, mm); + %put *%ll(2)*%ll(3)*%ll(4)*%ll(5)*%ll(6)**%ll(7)*%ll(8)*; + + %put *%mm(10)**%mm(11)*%mm(12)*%mm(13)*; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 2.** Error handling. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %appendArray(ll, ) + %appendArray(, mm) + + %appendArray(noExistA, noExistB) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +--- + + + +## >>> `%appendCell()` macro: <<< ############## + +The `%appendCell()` macro allows to append +a macrovariable to a macroarray created by the `%array()` macro. + +Dimensions of the macroarray are extended. + +The `%appendCell()` macro executes like a pure macro code. + +### SYNTAX: #################################################################### + +The basic syntax is the following, the `<...>` means optional parameters: +~~~~~~~~~~~~~~~~~~~~~~~sas +%appendCell( + first + ,second + ,hilo +) +~~~~~~~~~~~~~~~~~~~~~~~ + +**Arguments description**: + +1. `first` - *Required*, a name of a macroarray created by the `%array()` macro. + +2. `second` - *Required*, a name of a macrovariable to be append to the macroarray. + +3. `hilo` - *Required*, if `H` macrovariable is appended at the end + if `L` macrovariable is appended at the beginning +); + + + +### EXAMPLES AND USECASES: #################################################### + +**EXAMPLE 1.** Create two macro wrappers. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %* Macro wrapper to append a macrovariable to the end of a macroarray; + %macro appendHC(array,cell); + %appendCell(&array.,&cell.,H) + %mend appendHC; + + %* macro wrapper to append a macrovariable to the beginning of a macroarray; + %macro appendLC(array,cell); + %appendCell(&array.,&cell.,L) + %mend appendLC; + + + %* create macroarrays X and variables W,Y,Z; + + %array(X[2:4] $ ("AAA", "BBB", "CCC"), macarray=Y) + %let W=1; + %let Y=2; + %let Z=3; + %put *%do_over(X)*&=W*&=Y*&=Z*; + + %put BEFORE *%do_over(X)**&=xLBOUND*&=xHBOUND*&=xN*; + %appendCell(X,Y,H) + %put AFTER1 *%do_over(X)**&=xLBOUND*&=xHBOUND*&=xN*; + + %appendLC(X,W) + %put AFTER2 *%do_over(X)**&=xLBOUND*&=xHBOUND*&=xN*; + + %appendHC(X,Z) + %put AFTER3 *%do_over(X)**&=xLBOUND*&=xHBOUND*&=xN*; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 2.** Error handling +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %appendCell(X,Y,blahblah) + + %appendCell(X,,H) + %appendCell(,Y,H) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**EXAMPLE 3.** Adding variable below lower bound. +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(zero[0:2] $ ("AAA", "BBB", "CCC"), macarray=Y) + %let belowzero=zzz; + + %put BEFORE *%do_over(zero)**&=zeroLBOUND*&=zeroHBOUND*&=zeroN*; + %appendCell(zero,belowzero,L) + %put AFTER *%do_over(zero)**&=zeroLBOUND*&=zeroHBOUND*&=zeroN*; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +--- + + + +## >>> `%array()` macro: <<< ####################### + +The code of a macro was inspired by +*Ted Clay's* and *David Katz's* macro `%array()`. + +The `%array()` macro version provided in the package +is designed to facilitate +the idea of macro array concept, i.e. *a list of +macrovariables with common prefix and numerical suffixes*. +Usually such construction is then resolved by +double ampersand syntax, e.g. `&&perfix&i` or similar one. + +What is new/extension to the `%array()` macro concept are: + +0. The syntax is closer to the data step one. +1. It is a pure macro code (it can be executed in any place + of 4GL code), this includes generating macro arrays out + of datasets. +2. When a macroarrray is created it allows also to generate + a new macro (named the same as the array name) and replace + the double ampersand syntax with more array looking one, + i.e. for array ABC user can have `%ABC(1)`, `%ABC(2)`, or `%ABC(&i)` + constructions. +3. The array macro allows to use data step functions to generate + array's entries. + +The `%array()` macro executes like a pure macro code. + +### SYNTAX: ################################################################### + +The basic syntax is the following, the `<...>` means optional parameters: +~~~~~~~~~~~~~~~~~~~~~~~sas +%array( + array + <,function=> + <,before=> + <,after=> + <,vnames=N> + <,macarray=N> + <,ds=> + <,vars=> + <,q=> +) +~~~~~~~~~~~~~~~~~~~~~~~ + +**Arguments description**: + +1. `array` - *Required*, an array name and a declaration/definition of an array,
+ e.g. `myArr[*] x1-x3 (4:6)`
+ or `myBrr[*] $ y1-y3 ("a" "b" "c")`
+ or `myCrr[3] $ ("d d d" "e,e,e" "f;f;f")`
+ or `myDrr p q r s`.
+ Macrovariables created by the macro are *global*. + If an array name is `_` (single underscore) then attached variables + list names are used, a call of the form: + `%array(_[*] p1 q2 r3 s4 (-1 -2 -3 -4))` + will create macrovariables: `p1`, `q2`, `r3`, and `s4` with respective + values: `-1`, `-2`, `-3`, and `-4`.
+ Three additional *global* macrovariables: + `LBOUND`, `HBOUND`, and `N` + are generated with the macroarray. See examples for more use-cases. + +* `function=` - *Optional*, a function or an expression to be applied to all array cells, + `_I_` is as array iterator, e.g. `_I_ + rand("uniform")`. + +* `before=` - *Optional*, a function or an expression to be added before looping through + array, e.g. `call streaminit(123)`. + +* `after=` - *Optional*, a function or an expression to be added after looping through + array, e.g. `call sortn(ABC)`. + +* `vnames=N` - *Optional*, default value `N`, if set to `Y`/`YES` then macroarray is built based + on variables names instead values, e.g. + `%array(myArr[*] x1-x3 (4:6), vnames=Y)` + will use `x1`, `x2`, and `x3` as values instead `4`, `5`, and `6`. + +* `macarray=N` - *Optional*, default value `N`, if set to `Y`/`YES` then a macro, named with the array + name, is compiled to create convenient envelope for multiple ampersands, e.g. + `%array(myArr[*] x1-x3 (4:6), macarray=Y)` + will create `%myArr(J)` macro which will allow to extract "data" + from macroarray like: + `%let x = %myArr(1);` + or when used with second parameter equal `I` (insert) allow to overwrite macroarrays + value: + `%let %myArr(17,i) = 42;` + If set to `M` then for a given array name the macro symbols table is scanned for + macrovariables with prefix like the array name and numeric suffixes, + then the minimum and the maximum index is determined + and all not existing global macrovariables are created and + a macro is generated in the same way as for the `Y` value. + +* `ds=` - *Optional*, use a dataset as a basis for a macroarray data, + if used by default overwrites use of the `array` parameter, honors `macarray=` + argument, dataset options are allowed, e.g. `sashelp.class(obs=5)` + +* `vars=` - *Optional*, a list of variables used to create macroarrays from a dataset, + the list format can be as follows (`<...>` means optional): + `variable1 <... variableN>` + delimiters are hash(`#`) and pipe(`|`), currently only space + is supported as separator, the meaning of `#` and `|` delimiters + will be explained in the following example: + if the `vars = height#h weight weight|w age|` value is provided + then the following macroarrays will be created:
+ 1) macroarray "H" with ALL(`#`) values of variable "height"
+ 2) macroarray "WEIGHT" with ALL(no separator is equivalent to #) + values of variable "weight"
+ 3) macroarray "W" with UNIQUE(|) values of variable "weight" and
+ 4) macroarray "AGE" with UNIQUE(|) values of variable "age". + +* `q=` - *Optional*, indicates (when set to `1`) if the value be surrounded by quotes. + It uses `quote(cats(...))` combo under the hood. Default value is `0`. + Ignored for `macarray=M`. + + +--- + +### EXAMPLES AND USECASES: #################################################### + + +**EXAMPLE 1.** Basic use-case. + Creating macroarray like in the array statement. + Values not variables names are used by default. + Different types of brackets are allowed. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(a[*] x1-x5 (1:5)) + + %array(b{5} (5*17), q=1) + + %* Mind the $ since it is a character array!; + %array(c(3) $ 10 ("a A" "b,B" "c;C")) + + %array(d x1-x5 (5 4 3 2 1)) + %put _user_; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 2.** Index ranges. + If range starts < 0 then it is shifted to 0. + In case when range is from `1` to `M` + then macrovariable `N` is set to `M` + In case when range is different + the `N` returns number of + elements in the array `(Hbound - Lbound + 1)`. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(d[-2:2] $ ("a" "b" "c" "d" "e")) + %put &=dLBOUND. &=dHBOUND. &=dN.; + %put &=d0. &=d1. &=d2. &=d3. &=d4.; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 3.** Functions. + It is possible to assign value of a function + or an expression to a cell of the array, + e.g. `array[_I_] = function(...)`. + You can use an iterator in a function. + As in case of usual arrays it is `_I_`. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(e[-3:3] $, function = "A" ) + %put &=eLBOUND. &=eHBOUND. &=eN.; + %put &=e0. &=e1. &=e2. &=e3. &=e4. &=e5. &=e6.; + + %array(f[-3:3], function = (2**_I_) ) + %put &=fLBOUND. &=fHBOUND. &=fN.; + %put &=f0. &=f1. &=f2. &=f3. &=f4. &=f5. &=f6.; + + %array(g[0:2], function = ranuni(123) ) + %put &=gLBOUND. &=gHBOUND. &=gN.; + %put &=g0. &=g1. &=g2.; + + %* Or something more complex; + %array(gg[0:11] $ 11, function = put(intnx("MONTH", '1jun2018'd, _I_, "E"), yymmn.), q=1) + %put &=ggLBOUND. &=ggHBOUND. &=ggN.; + %put &=gg0 &=gg1 &=gg2 ... &=gg11; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 4.** Functions cont. + If there is need for set-up something *before* or *after*: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(h[10:12] + ,function = rand('Uniform') + ,before = call streaminit(123) + ,after = call sortn(of h[*]) + ) + %put &=h10. &=h11. &=h12.; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 5.** Fibonacci series. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(i[1:10] (10*0) + ,function = ifn(_I_ < 2, 1, sum(i[max(_I_-2,1)], i[max(_I_-1,2)]) ) ) + %put &=i1 &=i2 &=i3 &=i4 &=i5 &=i6 &=i7 &=i8 &=i9 &=i10; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 6a.** Quoted "Uppercas Letters" + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(UL[26] $, function = byte(rank("A")+_I_-1) , q=1) + %put &=UL1 &=UL2 ... &=UL25 &=UL26; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 6b.** "Lowercase Letters" + Extended by `macarray=Y` option and + the input mode support (with `I`). + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(ll[26] $, function = byte(rank("a")+_I_-1), macarray=Y) + %put *%ll(&llLBOUND.)*%ll(3)*%ll(4)*%ll(5)*...*%ll(25)*%ll(&llHBOUND.)*; + + %* The range handling, warning; + %put *%ll(265)*; + + %* The input mode; + %put *before:*%ll(2)*; + %let %ll(2,I) = bbbbb; + %put *after: *%ll(2)*; + + %* The range handling, error; + %let %ll(265,I) = bbb; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 7.** The use of `vnames=Y` + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(R R1978-R1982) + %put &=R1 &=R2 &=R3 &=R4 &=R5; + + %array(R R1978-R1982 (78:82)) + %put &=R1 &=R2 &=R3 &=R4 &=R5; + + %array(R R1978-R1982 (78:82), vnames=Y) + %put &=R1 &=R2 &=R3 &=R4 &=R5; + + %array(R R1978-R1982, vnames=Y) + %put &=R1 &=R2 &=R3 &=R4 &=R5; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 8.** A "no name" array i.e. the `_[*]` array + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(_[*] x1-x5 (1:5)) + %put _user_; + + %array(_[*] p q r s (4*42)) + %put _user_; + + %* If no variables names than use _1 _2 ... _N; + %array(_[4] (-1 -2 -3 -4)) + %put &=_1 &=_2 &=_3 &=_4; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 9.** Pure macro code can be used in a data step. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + data test1; + set sashelp.class; + %array(ds[*] d1-d4 (4*17)) + a1 = &ds1.; + a2 = &ds2.; + a3 = &ds3.; + a4 = &ds4.; + run; + + data test2; + set sashelp.class; + %array(_[*] j k l m (4*17)) + a1 = &j.; + a2 = &k.; + a3 = &l.; + a4 = &m.; + run; + + data test3; + set sashelp.class; + %array(alpha[*] j k l m (101 102 103 104), macarray=Y) + a1 = %alpha(1); + a2 = %alpha(2); + a3 = %alpha(3); + a4 = %alpha(4); + a5 = %alpha(555); + run; + + data test4; + set sashelp.class; + %array(beta[*] j k l m (101 102 103 104), vnames=Y, macarray=Y) + a1 = "%beta(1)"; + a2 = "%beta(2)"; + a3 = "%beta(3)"; + a4 = "%beta(4)"; + a5 = "%beta(555)"; + run; + + data test5; + set sashelp.class; + %array(gamma[4] $ 12 ("101" "102" "103" "104"), macarray=Y) + a1 = "%gamma(1)"; + a2 = "%gamma(2)"; + a3 = "%gamma(3)"; + a4 = "%gamma(4)"; + a5 = "%gamma(555)"; + run; + + data test6; + set sashelp.class; + %array(ds = sashelp.cars, vars = Cylinders|, macarray=Y) + a0 = %Cylinders(0); + a1 = %Cylinders(1); + a2 = %Cylinders(2); + a3 = %Cylinders(3); + a4 = %Cylinders(4); + a5 = %Cylinders(555); + run; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 10.** Creating an array from a dataset, basic case. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(ds = sashelp.class, vars = height weight age) + %put _user_; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 11. Creating an array from a dataset, advanced. + If: `vars = height#h weight weight|w age|` + then create: + 1. macroarray "h" with ALL(#) values of variable "height" + 2. macroarray "weight" with ALL(no separator is equivalent to #) values of variable "weight" + 3. macroarray "w" with UNIQUE(|) values of variable "weight" + 4. macroarray "age" with UNIQUE(|) values of variable "age" + Currently the only separator in VARS is a space. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(ds = sashelp.class, vars = height#h weight weight|w age|, q=1) + %put _user_; + + %array(ds = sashelp.class, vars = height#hght weight weight|wght age|, macarray=Y, q=1) + %put *%hght(&hghtLBOUND.)**%weight(2)**%wght(&wghtHBOUND.)**%age(3)*; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 12.** Creating an array from a dataset with dataset options + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(ds = sashelp.cars(obs=100 where=(Cylinders=6)), vars = Make| Type| Model, macarray=Y) + %put *%make(&makeLBOUND.)*%Model(2)*%Model(3)*%Model(4)*%type(&typeHBOUND.)*; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 13.** Creating an array and macro from existing list of macrovariables + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %let myTest3 = 13; + %let myTest6 = 16; + %let myTest9 = 19; + + %array(myTest, macarray=M, q=1) + %do_over(myTest, phrase = %nrstr(%put *&_I_.*%myTest(&_I_.)*;)) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +--- + + + +## >>> `%concatArrays()` macro: <<< ########### + +The `%concatArrays()` macro allows to concatenate +two macroarrays created by the `%array()` macro. + +By default values of the second macroarray are removed. + +Dimensions of the first macroarray are extended. + +The `%concatArrays()` macro executes like a pure macro code. + +### SYNTAX: ##################################################################### + +The basic syntax is the following, the `<...>` means optional parameters: +~~~~~~~~~~~~~~~~~~~~~~~sas +%concatArrays( + first + ,second + <,removeSecond=Y> +) +~~~~~~~~~~~~~~~~~~~~~~~ + +**Arguments description**: + +1. `first` - *Required*, a name of a macroarray created by the `%array()` macro. + +2. `second` - *Required*, a name of a macroarray created by the `%array()` macro. + +* `removeSecond=Y` - *Optional*, default value `Y`, if set to `Y` then + the second array is removed. + + + + +### EXAMPLES AND USECASES: #################################################### + +**EXAMPLE 1.** Concatenate macroarrays LL and MM. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(ll[2:4] $ 12, + function = quote(put(today() + 10*_I_, yymmdd10.)), + macarray=Y + ) + %array(mm[10:13] $ 12000, + function = quote(repeat("A",123*_I_)), + macarray=Y + ) + %put *%ll(2)*%ll(3)*%ll(4)*; + + %concatArrays(ll, mm); + %put *%ll(2)*%ll(3)*%ll(4)*%ll(5)*%ll(6)**%ll(7)*%ll(8)*; + + %put *%mm(10)**%mm(11)*%mm(12)*%mm(13)*; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 2.** Error handling. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %concatArrays(ll, ) + %concatArrays(, mm) + + %concatArrays(noExistA, noExistB) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +--- + + + +## >>> `%deleteMacArray()` macro: <<< ####### + +The `%deleteMacArray()` macro allows to delete +macroarrays created by the `%array()` macro. + +The `%deleteMacArray()` macro executes like a pure macro code. + +### SYNTAX: ##################################################################### + +The basic syntax is the following, the `<...>` means optional parameters: +~~~~~~~~~~~~~~~~~~~~~~~sas +%deleteMacArray( + arrs + <,macarray=N> +) +~~~~~~~~~~~~~~~~~~~~~~~ + +**Arguments description**: + +1. `arrs` - *Required*, a space separated list of manes + of macroarray created by the `%array()` macro. + +* `macarray=N` - *Optional*, indicator should a macro + associated with macroarray to be deleted? + If `Y` or `YES` then the associated macro is deleted. + + + + +## >>> `%do_over()` macro: <<< ###################### + +The code of the macro was inspired by +*Ted Clay's* and *David Katz's* macro `%do_over()`. + +The `%DO_OVER()` macro allows to iterate over macroarray created with +the `macarray=Y` parameter of the `%ARRAY()` macro. + +The `%do_over()` macro executes like a pure macro code. + +### SYNTAX: ##################################################################### + +The basic syntax is the following, the `<...>` means optional parameters: +~~~~~~~~~~~~~~~~~~~~~~~sas +%do_over( + array + <,phrase=%nrstr(%&array(&_I_.))> + <,between=%str( )> + <,which = > +) +~~~~~~~~~~~~~~~~~~~~~~~ + +**Arguments description**: + +1. `array` - *Required*, indicates a macroarray which metadata (Lbound, Hbouns) + are to be used to loop in the `%do_over()` + +* `phrase=` - *Optional*, Default value `%nrstr(%&array(&_I_.))`, + a statement to be called in each iteration + of the internal do_over's loop. Loop iterator is `_I_`, + if you want to use `_I_` or array name + [e.g. `%myArr(&_I_.)`] *enclose it* in the `%NRSTR()` + macro quoting function. + +* `between=` - *Optional*, default value `%str( )` (space), + a statement to be called in between each + iteration of the internal do_over loop. + If macroquoted (e.g. `%str( + )`) then the `%unquote()` + function is automatically applied. + +* `which=` - *Optional*, a _SPACE_ separated list of indexes which + should be used to iterate over selected macroarray. + Possible special characters are `H` and `L` which means + *high* and *low* bound of an array, list could be set with + colons(`:`) in form of `start:end:by` (*no spaces between!*), + if `by` is omitted the default is `1`. If possible use + `1:5` rather `1 2 3 4 5` since the firs works faster. + + + +### EXAMPLES AND USECASES: #################################################### + +**EXAMPLE 1.** Simple looping. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(beta[*] j k l m (101 102 103 104), vnames=Y, macarray=Y) + + %put #%do_over(beta)#; + + %put #%do_over(beta, phrase=%nrstr("%beta(&_I_.)"), between=%str(,))#; + + data test1; + %array(beta[*] j k l m (101 102 103 104), vnames=Y, macarray=Y) + %do_over(beta, phrase=%nrstr(a&_I_. = "%beta(&_I_.)";)) + put _all_; + run; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 2.** Multiple arrays looping. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(alpha[*] j k l m n, vnames=Y, macarray=Y) + %array( beta[5] $ , function = "a", macarray=Y) + %array(gamma[4] (101 102 103 104), macarray=Y) + + data test2; + call streaminit(123); + %do_over(beta + , phrase = %nrstr(%beta(&_I_.) = %gamma(&_I_.) * rand('Uniform'); output;) + , between = put _all_; + ); + put _all_; + run; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 3.** Multiple arrays looping, cont. + Create multiple datasets. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %do_over(beta + , phrase = %nrstr( + data %alpha(&_I_.)2; + call streaminit(123); + %beta(&_I_.)x = %gamma(&_I_.) * rand('Uniform'); + output; + run; + ) + ) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 4.** Multiple arrays looping, cont. + Create multiple datasets using a macro. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %macro doit(ds, var=a, val=1); + data &ds.; + call streaminit(123); + &var. = &val. * rand('Uniform'); + output; + run; + %mend doit; + + %do_over(beta + , phrase = %nrstr( + %DOIT(%alpha(&_I_.)1, var = %beta(&_I_.), val = %gamma(&_I_.)) + ) + ) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 5.** `%do_over()` inside `%array()` + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(test[*] x1-x12 (1:12), macarray=Y) + + %put **%test(1)**%test(12)**; + + %put #%do_over(test)#; + + %array(abc[*] x1-x12 (%do_over(test,phrase=%nrstr(%eval(100-%test(&_I_.))))), macarray=Y) + + %put **%abc(1)**%abc(12)**; + + %put #%do_over(abc)#; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 6.** Looping over array with *macroquoted* separator. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(alpha[11] (5:15), macarray=Y) + + %let x = %do_over(alpha + , phrase = %NRSTR(%alpha(&_I_.)) + , between= %str( + ) + ); + %put &=x.; + %put %sysevalf(&x.); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 7.** Working with the `WHICH=` optional parameter + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(test[*] x01-x12, vnames= Y, macarray=Y) + + %put #%do_over(test)#; + + %put #%do_over(test, which= 1 3 5)#; + + %put #%do_over(test, which= 1:5)#; + + %put #%do_over(test, which= 1:5:2 7 8)#; + + %put #%do_over(test, which= L:H l:h)#; + + %put #%do_over(test, which= L:3 10:h)#; + + %put #%do_over(test, which= L:H h:l:-1 13 14)#; + + %put #%do_over(test, which= %eval(1+1):%eval(5+1))#; + + %put #%do_over(test, which= L:H h:l:-1 13 14, between=%str(,))#; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +--- + + + +## >>> `%do_over2()` macro: <<< #################### + +The code of the macro was inspired by +*Ted Clay's* and *David Katz's* macro `%do_over()`. + +The `%DO_OVER2()` macro allows to iterate over *two* macroarray created with +the `macarray=Y` parameter of the `%ARRAY()` macro. + +The `%do_over2()` macro executes like a pure macro code. + +### SYNTAX: ##################################################################### + +The basic syntax is the following, the `<...>` means optional parameters: +~~~~~~~~~~~~~~~~~~~~~~~sas +%do_over2( + arrayI + ,arrayJ + <,phrase=%nrstr(%&arrayI(&_I_.) %&arrayJ(&_J_.))> + <,between=%str( )> +) +~~~~~~~~~~~~~~~~~~~~~~~ + +**Arguments description**: + +1. `arrayI` - Required, indicates the first macroarray which metadata (Lbound, Hbouns) + are to be used in the outer loop in the `%do_over2()` + +2. `arrayJ` - Required, indicates the second macroarray which metadata (Lbound, Hbouns) + are to be used in the inner loop in the `%do_over2()` + +* `phrase=` - *Optional*, default value `%nrstr(%&arrayI(&_I_.) %&arrayJ(&_J_.))`, + a statement to be called in each iteration + of the *inner* loop. The outer loop iterator is `_I_`, + the inner loop iterator is `_J_`, + if you want to use `_I_`, `_J_`, or arrays names + [e.g. `%myArr(&_I_.)`] *enclose them* in the `%NRSTR()` + macro quoting function. + +* `between=` - *Optional*, default value `%str( )` (space), + a statement to be called in between each + iteration of the internal do_over2 loop. + If macroquoted (e.g. `%str( + )`) then the `%unquote()` + function is automatically applied. + + + + +### EXAMPLES AND USECASES: #################################################### + +**EXAMPLE 1.** Looping over two arrays. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(alpha[*] j k l m n, vnames=Y, macarray=Y) + %array( beta[4] (101 102 103 104), macarray=Y) + + %put *%do_over2(alpha, beta + , phrase = %NRSTR((%alpha(&_I_.), %beta(&_J_))) + )*; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 2.** Looping over two arrays with a separator. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(alpha[11] (5:15), macarray=Y) + %array( beta[ 4] (101 102 103 104), macarray=Y) + + %let x = %do_over2(alpha, beta + , phrase = %NRSTR((%alpha(&_I_.) * %beta(&_J_))) + , between= + + ); + %put &=x.; + %put %sysevalf(&x.); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 3.** Looping over two arrays with *macroquoted* separator. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(alpha[11] (5:15), macarray=Y) + %array( beta[ 4] (101 102 103 104), macarray=Y) + + %let x = %do_over2(alpha, beta + , phrase = %NRSTR((%alpha(&_I_.) * %beta(&_J_))) + , between= %str( + ) + ); + %put &=x.; + %put %sysevalf(&x.); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +--- + + + +## >>> `%do_over3()` macro: <<< #################### + +The code of the macro was inspired by +*Ted Clay's* and *David Katz's* macro `%do_over()`. + +The `%DO_OVER3()` macro allows to iterate over *three* macroarray created with +the `macarray=Y` parameter of the `%ARRAY()` macro. + +The `%do_over3()` macro executes like a pure macro code. + +### SYNTAX: ##################################################################### + +The basic syntax is the following, the `<...>` means optional parameters: +~~~~~~~~~~~~~~~~~~~~~~~sas +%do_over2( + arrayI + ,arrayJ + ,arrayK + <,phrase=%nrstr(%&arrayI(&_I_.) %&arrayJ(&_J_.) %&arrayK(&_K_.))> + <,between=%str( )> +) +~~~~~~~~~~~~~~~~~~~~~~~ + +**Arguments description**: + +1. `arrayI` - *Required*, indicates the first macroarray which metadata (Lbound, Hbouns) + are to be used in the outer loop in the `%do_over3()` + +2. `arrayJ` - *Required*, indicates the second macroarray which metadata (Lbound, Hbouns) + are to be used in the inner loop in the `%do_over3()` + +3. `arrayK` - *Required*, indicates the third macroarray which metadata (Lbound, Hbouns) + are to be used in the inner loop in the `%do_over3()` + +* `phrase=` - *Optional*, default value `%nrstr(%&arrayI(&_I_.) %&arrayJ(&_J_.) %&arrayK(&_K_.))`, + a statement to be called in each iteration + of the *inner* loop. The *outer* loop iterator is `_I_`, + the *middle* loop iterator is `_J_`, the *inner* loop iterator is `_K_`, + if you want to use `_I_`, `_J_`, `_K_`, or arrays names + [e.g. `%myArr(&_I_.)`] *enclose them* in the `%NRSTR()` + macro quoting function. + +* `between=` - *Optional*, default value `%str( )` (space), + a statement to be called in between each + iteration of the internal do_over2 loop. + If macroquoted (e.g. `%str( + )`) then the `%unquote()` + function is automatically applied. + + + + +### EXAMPLES AND USECASES: #################################################### + +**EXAMPLE 1.** Looping over 3 macroarrays. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(a1_[2] (0 1), macarray=Y) + %array(a2_[2] (2 3), macarray=Y) + %array(a3_[2] (4 5), macarray=Y) + + %do_over3(a1_, a2_, a3_ + , phrase = %NRSTR(%put (%a1_(&_I_.), %a2_(&_J_), %a3_(&_K_));) + ) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**EXAMPLE 2.** Looping 3 times over a macroarray. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(a[0:2] (0 1 2), macarray=Y) + + %do_over3(a, a, a + , phrase = %NRSTR(%put (%a(&_I_.), %a(&_J_), %a(&_K_));) + ) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +--- + + + +## >>> `%make_do_over()` macro: <<< ########### + +The code of the macro was inspired by +*Ted Clay's* and *David Katz's* macro `%do_over()`. + +The `%make_do_over()` macro allows to generate +the `%DO_OVER()` macros. It works *only* for *n>3*! + +The `%make_do_over()` macro does *not* executes like a pure macro code. + +### SYNTAX: ##################################################################### + +The basic syntax is the following, the `<...>` means optional parameters: +~~~~~~~~~~~~~~~~~~~~~~~sas +%make_do_over( + size +) +~~~~~~~~~~~~~~~~~~~~~~~ + +**Arguments description**: + +1. `size` - *Required*, indicates the number of dimensions + (i.e. inner loops) of the `%DO_OVER()` macro. + + + + +### EXAMPLES AND USECASES: #################################################### + +**EXAMPLE 1.** Code of created "4-loop" `%DO_OVER4()` macro + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %macro do_over4( + arrayI1, + arrayI2, + arrayI3, + arrayI4, + phrase=%nrstr( + %&arrayI1(&_I1_.) + %&arrayI2(&_I2_.) + %&arrayI3(&_I3_.) + %&arrayI3(&_I4_.) + ), + between=%str( ) + ); + %local _I1_ _I2_ _I3_ _I4_; + %do _I1_ = &&&arrayI1.LBOUND %to &&&arrayI1.HBOUND; + %do _I2_ = &&&arrayI2.LBOUND %to &&&arrayI2.HBOUND; + %do _I3_ = &&&arrayI3.LBOUND %to &&&arrayI3.HBOUND; + %do _I4_ = &&&arrayI4.LBOUND %to &&&arrayI4.HBOUND; + %if not ( + &_I1_. = &&&arrayI1.LBOUND + AND &_I2_. = &&&arrayI2.LBOUND + AND &_I3_. = &&&arrayI3.LBOUND + AND &_I4_. = &&&arrayI4.LBOUND + ) + %then %do;%unquote(&between.)%end;%unquote(%unquote(&phrase.)) + %end; + %end; + %end; + %end; + %mend do_over4; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 2.** Create a "4-loop" `%DO_OVER4()` macro + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %make_do_over(4); + + %array(a1_[2] (0 1), macarray=Y) + + %do_over4(a1_, a1_, a1_, a1_ + , phrase = %NRSTR(%put (%a1_(&_I1_.), %a1_(&_I2_), %a1_(&_I3_), %a1_(&_I4_));) + ) + + %put *%do_over4(a1_, a1_, a1_, a1_ + , between = * + )*; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**EXAMPLE 3.** Create a "5-loop" `%DO_OVER5()` macro + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %make_do_over(5); + + %array(a1_[2] (0 1), macarray=Y) + + %do_over5(a1_, a1_, a1_, a1_, a1_ + , phrase = %NRSTR(%put (%a1_(&_I1_.), %a1_(&_I2_), %a1_(&_I3_), %a1_(&_I4_), %a1_(&_I5_));) + ) + + %put *%do_over5(a1_, a1_, a1_, a1_, a1_ + , between = * + )* + ; + + options nomprint; + data test2; + %do_over5(a1_, a1_, a1_, a1_, a1_ + , phrase = %NRSTR(x1 = %a1_(&_I1_.); x2 = %a1_(&_I2_); x3 = %a1_(&_I3_); x4 = %a1_(&_I4_); x5 = %a1_(&_I5_);) + , between = output; + ) + output; + run; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 4.** Create all from 6 to 10 "do_overs" + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(loop[6:10] (6:10), macarray=Y) + %do_over(loop + , phrase = %nrstr( + %make_do_over(%loop(&_I_.)) + ) + ); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +--- + +## >>> `%mcHashTable()` macro: <<< ####################### + +The `%mcHashTable()` macro provided in the package +is designed to facilitate the idea of a "macro hash table" +concept, i.e. *a list of macrovariables with common prefix +and suffixes generated as a hash digest* which allows +to use values other than integers as indexes. + +The `%mcHashTable()` macro allows to generate other macros +which behaves like hash tables or dictionaries. See examples below. + +The `%mcHashTable()` macro executes like a pure macro code. + +### SYNTAX: ################################################################### + +The basic syntax is the following, the `<...>` means optional parameters: +~~~~~~~~~~~~~~~~~~~~~~~sas +%mcHashTable( + H + <,METHOD> + <,HASH=> +) +~~~~~~~~~~~~~~~~~~~~~~~ + +**Arguments description**: + +1. `H` - *Required*, a hash table macro name and a declaration/definition, + e.g. `mcHashTable(HT)`. It names a macro which is generated by + the `%mcHashTable()` macro. Provided name cannot be empty + or an underscore (`_`). No longer than *16* characters. + +2. `METHOD` - *Optional*, if empty (or DECLARE or DCL) then the code of + a macro hash table is compiled. + If `DELETE` then the macro hash table named by `H` and all + macrovariables named like "`&H._`" are deleted. + +* `HASH=` - *Optional*, indicates which hashing algorithms should be used, + available values are `CRC32` or `MD5`, the `CRC32` is the default. + +--- + +### THE CREATED MACRO `%&H.()`: #################################################### + +The created macro imitates behaviour of a hash table or a dictionary. +It is *not* dedicated for "long-ish" lists (above 1000 elements) since +the performance may be poor. + +The basic syntax is the following, the `<...>` means optional parameters: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%&H.( + METHOD + <,KEY=> + <,DATA=> +) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Arguments description**: + +1. `METHOD` - *Required*, indicate what behaviour should be executed. + Allowed values are: + - `ADD`, adds key and data portion to the macro hash table, + *multiple data portions* are available for one key. + - `FIND`, tests if given key exists in the macro hash table + and, if yes, returns data value associated with the key. + For multiple data portions see the `data=` parameter. + - `DP` (data portion) or `CHECK`, returns the number of data + portions for a given key. + - `CLEAR` removes all data and keys values. + - `KEYIDX`, allows to get data by the key index rather than value. + - `KEYVAL`, returns key value for a given key index. + - `CHECKIDX`, returns the number of data portions for + a given key index. + +* `KEY=` - *Optional*, provides key value for `ADD`, `FIND`,`DP`, `CHECK` + `CHECKIDX`, `KEYIDX`, and `KEYVAL` methods. Leading and trimming + spaces are removed from the value. + The `hashing(CRC32,...)` function or the `MD5(...)` function is + used to generate the hash. + +* `DATA=` - *Optional*, provides data value for the `ADD` method and + for the`FIND` method provides data portion number to be + extracted. Default value is `1` (used by the `FIND` method). + + +When macro is executed and when data are added the following types of +*global* macrovariables are created: +- `&H._########`, +- `&H._########_Xk`, +- `&H._########_Xi`, +- `&H._########_Xi_j`, +- `&H._KEYNUM`, +- and `&H._KEY_i`. + +The `#` represents value generated by the `hashing(CRC32,...)` function +or the `MD5(...)` function for the given key. + +The first type keeps information about possible collision for the key. + +The second type keeps information about value of a given key, +the `X` keeps the track of other colliding keys. + +The third type keeps information about number of data portions +for given key, the `X` keeps the track of other colliding keys. + +The fourth type keeps the data portion, the `j` indicates data portion number. + +The fifth type keeps the number of unique values of the key. + +The sixth type keeps the list of unique values of the key, +the `i` indicates key number. + +See examples below to see use cases. + +--- + +### EXAMPLES AND USECASES: #################################################### + + +**EXAMPLE 1.** Basic use-case. + Creating macro hash table, macro `HT` is generated. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%mcHashTable(HT) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Add elements to the `HT`. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%HT(ADD,key=x,data=17) +%HT(ADD,key=y,data=42) +%HT(ADD,key=z,data=303) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Add some duplicates for the key x. + See macrovariables created. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%HT(ADD,key=x,data=18) +%HT(ADD,key=x,data=19) + +%put _user_; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Check the number od data portions in macrohash + for the key `x` and non existing key `t`. +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%put ##%HT(DP,key=x)##; +%put ##%HT(DP,key=t)##; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Check the number od data portions in macrohash + for the key index 1 and 4. +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%put ##%HT(CHECKIDX,key=1)##; +%put ##%HT(CHECKIDX,key=4)##; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Prints first data values for various keys. + Key `t` does not exist in the macrohash. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%put #%HT(FIND,key=x)#; +%put #%HT(FIND,key=y)#; +%put #%HT(FIND,key=z)#; +%put #%HT(FIND,key=t)#; + +%put #%HT(FIND,key=x,data=2)#; +%put #%HT(FIND,key=x,data=3)#; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Print first and subsequent data values + for a given KeyIDX. Index `4` does not exist. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%put #%HT(KEYIDX,key=1)#; +%put #%HT(KEYIDX,key=2)#; +%put #%HT(KEYIDX,key=3)#; +%put #%HT(KEYIDX,key=4)#; + +%put #%HT(KEYIDX,key=1,data=2)#; +%put #%HT(KEYIDX,key=1,data=3)#; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Print the key values for a given KeyIDX. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%put #%HT(KEYVAL,key=1)#; +%put #%HT(KEYVAL,key=2)#; +%put #%HT(KEYVAL,key=3)#; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Clear and delete macro hash table `HT`. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%HT(CLEAR) +%mcHashTable(HT,DELETE) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 2.** Combine `CHECK` and `FIND` methods + with macros `%array()` and `%do_over()` + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%mcHashTable(H) +%H(ADD,key=x,data=17) +%H(ADD,key=x,data=18) +%H(ADD,key=x,data=19) + +%array(A[%H(CHECK,key=x)]); + +%put %do_over(A, phrase=%nrstr( + %H(FIND,key=x,data=&_i_) +), between = %str(,)); + +%mcHashTable(H,delete) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 3.** Populate macro hash table from a dataset. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%mcHashTable(CLASS) +%let t = %sysfunc(datetime()); +data _null_; + set sashelp.class; + call execute('%CLASS(ADD,key=' !! name !! ',data=' !! age !! ')'); + call execute('%CLASS(ADD,key=' !! name !! ',data=' !! weight !! ')'); + call execute('%CLASS(ADD,key=' !! name !! ',data=' !! height !! ')'); +run; +%put t = %sysevalf(%sysfunc(datetime()) - &t.); +%put _user_; +%CLASS(CLEAR) + + +%mcHashTable(CARS) +%let t = %sysfunc(datetime()); +data _null_; + set sashelp.cars; + call execute('%CARS(ADD,key=' !! catx("|",make,model) !! ',data=' !! MPG_CITY !! ')'); +run; +%put t = %sysevalf(%sysfunc(datetime()) - &t.); +%* %put _user_; +%CARS(CLEAR) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 4.** Data portion may require quoting and un-quoting.. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%mcHashTable(CODE) +%CODE(CLEAR) +%CODE(ADD,key=data, data=%str(data test; x = 42; run;)) +%CODE(ADD,key=proc, data=%str(proc print; run;)) +%CODE(ADD,key=macro,data=%nrstr(%put *****;)) + +%CODE(FIND,key=data) +%CODE(FIND,key=proc) +%unquote(%CODE(FIND,key=macro)) + +%mcHashTable(CODE,DELETE) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 5.** Longer lists. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%let size = 1000; + +%mcHashTable(AAA) +%mcHashTable(BBB) +%mcHashTable(CCC) +%mcHashTable(DDD) + +%let t = %sysfunc(datetime()); +data _null_; + do i = 1 to &size.; + call execute(cats('%AAA(ADD,key=A', i, ',data=', i, ')')); + end; +run; +%put t = %sysevalf(%sysfunc(datetime()) - &t.); +%put &=AAA_KEYSNUM; +%AAA(CLEAR) + +%let t = %sysfunc(datetime()); +data _null_; + do i = 1 to &size.; + call execute(cats('%BBB(ADD,key=B', i, ',data=', i, ')')); + call execute(cats('%BBB(ADD,key=B', i, ',data=', i+1, ')')); + end; +run; +%put t = %sysevalf(%sysfunc(datetime()) - &t.); +%put &=BBB_KEYSNUM; +%BBB(CLEAR) + +%let t = %sysfunc(datetime()); +data _null_; + t= datetime(); + do i = 1 to &size.; + call execute(cats('%CCC(ADD,key=C', i, ',data=', i, ')')); + end; + t = datetime() - t; + put t=; + t= datetime(); + do i = 1 to &size.; + call execute(cats('%CCC(ADD,key=C', i, ',data=', i+1, ')')); + end; + t = datetime() - t; + put t=; +run; +%put t = %sysevalf(%sysfunc(datetime()) - &t.); + +%let t = %sysfunc(datetime()); +data test; + do i = 1 to &size.; + x = resolve(cats('%CCC(FIND,key=C', i, ',data=1)')); + y = resolve(cats('%CCC(FIND,key=C', i, ',data=2)')); + output; + end; +run; +%put t = %sysevalf(%sysfunc(datetime()) - &t.); +%put &=CCC_KEYSNUM; +%CCC(CLEAR) + +%let t = %sysfunc(datetime()); +data _null_; + do i = 1 to &size.; + call execute(cats('%DDD(ADD,key=D,data=', i, ')')); + end; +run; +%put t = %sysevalf(%sysfunc(datetime()) - &t.); +%put &=DDD_KEYSNUM; +%put %DDD(CHECK,key=D); +%DDD(CLEAR) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 6.** Forbidden names. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%mcHashTable() +%mcHashTable(_) + +%mcHashTable(ABCDEFGHIJKLMNOPQ) %* bad; +%mcHashTable(ABCDEFGHIJKLMNOP) %* good; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**EXAMPLE 7.** Hashing algorithms. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%mcHashTable(H1,DCL,HASH=MD5) +%mcHashTable(H2,DECLARE,HASH=CRC32) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +--- + +## >>> `%mcDictionary()` macro: <<< ####################### + +The `%mcDictionary()` macro provided in the package +is designed to facilitate the idea of a "macro dictionary" +concept, i.e. *a list of macrovariables with common prefix +and suffixes generated as a hash digest* which allows +to use values other than integers as indexes. + +The `%mcDictionary()` macro allows to generate other macros +which behaves like a dictionary. See examples below. + +The `%mcDictionary()` macro executes like a pure macro code. + +### SYNTAX: ################################################################### + +The basic syntax is the following, the `<...>` means optional parameters: +~~~~~~~~~~~~~~~~~~~~~~~sas +%mcDictionary( + H + <,METHOD> +) +~~~~~~~~~~~~~~~~~~~~~~~ + +**Arguments description**: + +1. `H` - *Required*, a dictionary macro name and a declaration/definition, + e.g. `mcDictionary(HT)`. It names a macro which is generated by + the `%mcDictionary()` macro. Provided name cannot be empty + or an underscore (`_`). No longer than *16* characters. + +2. `METHOD` - *Optional*, if empty (or DECLARE or DCL) then the code of + a macro dictionary is compiled. + If `DELETE` then the macro dictionary named by `H` and all + macrovariables named like "`&H._`" are deleted. + +--- + +### THE CREATED MACRO `%&H.()`: #################################################### + +The created macro imitates behaviour of a dictionary. + +The basic syntax is the following, the `<...>` means optional parameters: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%&H.( + METHOD + <,KEY=> + <,DATA=> +) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Arguments description**: + +1. `METHOD` - *Required*, indicate what behaviour should be executed. + Allowed values are: + - `ADD`, adds key and data portion to the macro dictionary, + *multiple data portions* are NOT available for one key. + - `FIND`, tests if given key exists in the macro dictionary + and, if yes, returns data value associated with the key. + For multiple data portions see the `data=` parameter. + - `CHECK`, returns indicator if the key exists in dictionary. + - `DEL`, removes key and data portion from the macro dictionary. + - `LIST`, prints out a dictionary to the log. + - `CLEAR` removes all data and keys values. + +* `KEY=` - *Optional*, provides key value for `ADD`, `FIND`, `CHECK` + and `DEL` methods. + Leading and trimming spaces are removed from the value. + The `MD5(...)` function is used to generate the hash. + Default value is `_`. + +* `DATA=` - *Optional*, provides data value for the `ADD` method. + Default value is blank. + + +When macro is executed and when data are added the following types of +*global* macrovariables are created: +- `&H._########_K`, +- `&H._########_V`, +- `&H._KEYSNUM`. + +The `#` represents value generated by the `MD5(...)` function for the given key. + +The first type keeps information about the key. + +The second type keeps information about the value of a given key + +The third type keeps the number of unique values of the key. + +See examples below to see use cases. + +--- + +### EXAMPLES AND USECASES: #################################################### + + +**EXAMPLE 1.** Basic use-case. + Creating macro dictionary, macro `Dict` is generated. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%mcDictionary(Dict) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Add elements to the `Dict`. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%Dict(ADD,key=x,data=17) +%Dict(ADD,key=y y,data=42) +%Dict(ADD,key=z z z,data=303) + +%put _user_; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Add some duplicates for the key x. + See macrovariables created. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%Dict(ADD,key=x,data=18) + +%put _user_; + +%Dict(ADD,key=x,data=19) + +%put _user_; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Check for the key `x` and non existing key `t`. +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%put ##%Dict(CHECK,key=x)##; +%put ##%Dict(CHECK,key=t)##; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Prints data values for various keys. + Key `t` does not exist in the macrodictionary. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%put #%Dict(FIND,key=x)#; +%put #%Dict(FIND,key=y y)#; +%put #%Dict(FIND,key=z z z)#; +%put #%Dict(FIND,key=t)#; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + List dictionary content to the log. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%Dict(LIST); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Delete keys. + Key `t` does not exist in the macrodictionary. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%put #%Dict(DEL,key=z z z)#; +%put _user_; +%put #%Dict(DEL,key=t)#; +%put _user_; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Clear and delete macro dictionary `Dict`. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%Dict(CLEAR) +%put _user_; + +%mcDictionary(Dict,DELETE) +%put _user_; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 2.** Populate macro dictionary from a dataset. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%mcDictionary(CLASS) +%let t = %sysfunc(datetime()); +data _null_; + set sashelp.class; + call execute('%CLASS(ADD,key=' !! name !! ',data=' !! age !! ')'); +run; +%put t = %sysevalf(%sysfunc(datetime()) - &t.); +%put _user_; +%CLASS(CLEAR) + + +%mcDictionary(CARS) +%let t = %sysfunc(datetime()); +data _null_; + set sashelp.cars; + call execute('%CARS(ADD,key=' !! catx("|",make,model,type) !! ',data=' !! MPG_CITY !! ')'); +run; +%put t = %sysevalf(%sysfunc(datetime()) - &t.); +%put &=CARS_KEYSNUM.; +%CARS(LIST); +%CARS(CLEAR) +%put &=CARS_KEYSNUM.; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 3.** Data portion may require quoting and un-quoting.. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%mcDictionary(CODE) +%CODE(CLEAR) +%CODE(ADD,key=data, data=%str(data test; x = 42; run;)) +%CODE(ADD,key=proc, data=%str(proc print; run;)) +%CODE(ADD,key=macro,data=%nrstr(%put *****;)) + +%CODE(FIND,key=data) +%CODE(FIND,key=proc) +%unquote(%CODE(FIND,key=macro)) + +%CODE(LIST); + +%mcDictionary(CODE,DELETE) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 4.** Longer lists. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%let size = 1000; + +%mcDictionary(AAA) + +%let t = %sysfunc(datetime()); +data _null_; + do i = 1 to &size.; + call execute(cats('%AAA(ADD,key=A', i, ',data=', i, ')')); + end; +run; +%put t = %sysevalf(%sysfunc(datetime()) - &t.); +%put &=AAA_KEYSNUM; +%AAA(CLEAR) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 5.** Forbidden names. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%mcDictionary() +%mcDictionary(_) + +%mcDictionary(ABCDEFGHIJKLMNOPQ) %* bad; +%mcDictionary(ABCDEFGHIJKLMNOP) %* good; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +--- + +## >>> `%QzipArrays()` macro: <<< ####################### + +The zipArrays() and QzipArrays() macros +allow to use a function on elements of pair of +macro arrays. + +For two macroarrays the corresponding +elements are taken and the macro applies a function, provided by user, +to calculate result of the function on taken elements. + +When one of the arrays is shorter then elements are, by default, +"reused" starting from the beginning. But this behaviour can be altered. +See examples for the details. + +By default newly created macroarray name is concatenation +of first 13 characters of names of arrays used to create the new one, +e.g. if arrays names are `abc` and `def` then the result name is `abcdef`, +if arrays names are `abcd1234567890` and `efgh1234567890` then the result +name is `abcd123456789efgh123456789` + +The `zipArrays()` returns unquoted value [by `%unquote()`]. +The `QzipArrays()` returns quoted value [by `%superq()`]. + +See examples below for the details. + +The `%QzipArrays()` macro executes like a pure macro code. + +### SYNTAX: ################################################################### + +The basic syntax is the following, the `<...>` means optional parameters: +~~~~~~~~~~~~~~~~~~~~~~~sas +%QzipArrays( + first + ,second + <,function=> + <,operator=> + <,argBf=> + <,argMd=> + <,argAf=> + <,format=> + <,result=> + <,macarray=> + <,reuse=> +) +~~~~~~~~~~~~~~~~~~~~~~~ + +**Arguments description**: + +1. `first` - *Required*, a space separated list of texts. + +2. `second` - *Required*, a space separated list of texts. + +* `function = cat` - *Optional*, default value is `cat`, + a function which will be applied + to corresponding pairs of elements of + the first and the second list. + +* `operator =` - *Optional*, default value is empty, + arithmetic infix operator used with elements + the first and the second list. The first + list is used on the left side of the operator + the second list is used on the right side + of the operator. + +* `argBf =` - *Optional*, default value is empty, + arguments of the function inserted + *before* elements the first list. + If multiple should be comma separated. + +* `argMd =` - *Optional*, default value is empty, + arguments of the function inserted + *between* elements the first list and + the second list. + If multiple should be comma separated. + +* `argAf =` - *Optional*, default value is empty, + arguments of the function inserted + *after* elements the second list. + If multiple should be comma separated. + +* `format=` - *Optional*, default value is empty, + indicates a format which should be used + to format the result, does not work when + the `operator=` is used. + +* `result=` - *Optional*, default value is empty, + indicates a name of newly created macroarray, + by default created macroarray name is concatenation + of first 13 characters of names of arrays used + to create the new one. + +* `macarray=N` - *Optional*, default value is `N`, + if set to `Y`/`YES` then a macro, named with + the array name, is compiled to create convenient + envelope for multiple ampersands, see the + `%array()` macro for details. + +* `reuse=Y` - *Optional*, default value is `Y`, + when one of the arrays is shorter then elements + are *reused* starting from the beginning. + If `CP` then function is executed on the *Cartesian + product* of arrays elements. Any other value will + cut the process with the end of the shorter array. + See examples for the details. + +### EXAMPLES AND USECASES: #################################################### + +See examples in `%zipArrays()` help for the details. + +--- + +## >>> `%zipArrays()` macro: <<< ####################### + +The zipArrays() and QzipArrays() macros +allow to use a function on elements of pair of +macro arrays. + +For two macroarrays the corresponding +elements are taken and the macro applies a function, provided by user, +to calculate result of the function on taken elements. + +When one of the arrays is shorter then elements are, by default, +"reused" starting from the beginning. But this behaviour can be altered. +See examples for the details. + +By default newly created macroarray name is concatenation +of first 13 characters of names of arrays used to create the new one, +e.g. if arrays names are `abc` and `def` then the result name is `abcdef`, +if arrays names are `abcd1234567890` and `efgh1234567890` then the result +name is `abcd123456789efgh123456789` + +The `zipArrays()` returns unquoted value [by `%unquote()`]. +The `QzipArrays()` returns quoted value [by `%superq()`]. + +See examples below for the details. + +The `%zipArrays()` macro executes like a pure macro code. + +### SYNTAX: ################################################################### + +The basic syntax is the following, the `<...>` means optional parameters: +~~~~~~~~~~~~~~~~~~~~~~~sas +%zipArrays( + first + ,second + <,function=> + <,operator=> + <,argBf=> + <,argMd=> + <,argAf=> + <,format=> + <,result=> + <,macarray=> + <,reuse=> +) +~~~~~~~~~~~~~~~~~~~~~~~ + +**Arguments description**: + +1. `first` - *Required*, a space separated list of texts. + +2. `second` - *Required*, a space separated list of texts. + +* `function = cat` - *Optional*, default value is `cat`, + a function which will be applied + to corresponding pairs of elements of + the first and the second list. + +* `operator =` - *Optional*, default value is empty, + arithmetic infix operator used with elements + the first and the second list. The first + list is used on the left side of the operator + the second list is used on the right side + of the operator. + +* `argBf =` - *Optional*, default value is empty, + arguments of the function inserted + *before* elements the first list. + If multiple should be comma separated. + +* `argMd =` - *Optional*, default value is empty, + arguments of the function inserted + *between* elements the first list and + the second list. + If multiple should be comma separated. + +* `argAf =` - *Optional*, default value is empty, + arguments of the function inserted + *after* elements the second list. + If multiple should be comma separated. + +* `format=` - *Optional*, default value is empty, + indicates a format which should be used + to format the result, does not work when + the `operator=` is used. + +* `result=` - *Optional*, default value is empty, + indicates a name of newly created macroarray, + by default created macroarray name is concatenation + of first 13 characters of names of arrays used + to create the new one. + +* `macarray=N` - *Optional*, default value is `N`, + if set to `Y`/`YES` then a macro, named with + the array name, is compiled to create convenient + envelope for multiple ampersands, see the + `%array()` macro for details. + +* `reuse=Y` - *Optional*, default value is `Y`, + when one of the arrays is shorter then elements + are *reused* starting from the beginning. + If `CP` then function is executed on the *Cartesian + product* of arrays elements. Any other value will + cut the process with the end of the shorter array. + See examples for the details. + +### EXAMPLES AND USECASES: #################################################### + +**EXAMPLE 1.** Simple concatenation of elements: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%array(a[*] x1-x3 (1:3)) +%array(b[*] x1-x5 (11:15)) + +%put _user_; + +%zipArrays(a, b); +%put _user_; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 2.** Shorter list is "reused": +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%array(a[6] (1:6)) +%array(b[3] (10 20 30)) + +%zipArrays(a, b, result=A_and_B, macarray=Y); +%put %do_over(A_and_B); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 3.** Use of the `operator=`: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%array(c[0:4] (000 100 200 300 400)) +%array(d[2:16] (1002:1016)) + +%zipArrays(c, d, operator=+, result=C_plus_D, macarray=Y); +%put (%do_over(C_plus_D)); + +%put %C_plus_D(1); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 4.** If one of array names is empty or an array does not exist: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%array(a[6] (1:6)) +%array(b[3] (10 20 30)) + +%zipArrays(a, ); +%zipArrays(, b); + +%zipArrays(a, z); +%zipArrays(z, b); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 5.** Use of the `function=`: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%array(one[3] A B C, vnames=Y) +%array(two[5] p q r s t, vnames=Y) + +%zipArrays( + one +,two +,function = catx +,argBf = %str( ) +,format = $quote. +,macarray=Y +) +%put %do_over(onetwo); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 6.** To reuse or not to reuse, or maybe Cartesian product: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%array(e[3] (10 20 30)) +%array(f[2] (5:6)) + +%zipArrays(e, f, reuse=n, operator=+, macarray=Y, result=_noReuse); +%zipArrays(e, f, reuse=y, operator=+, macarray=Y, result=_yesReuse); +%zipArrays(e, f, reuse=cp, operator=+, macarray=Y, result=_cartProdReuse); + +%put %do_over(_noReuse); +%put %do_over(_yesReuse); +%put %do_over(_cartProdReuse); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 7.** Use middle argument: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%array(yr[3] (2018:2020)) +%array(mth[12] (1:12)) + +%zipArrays(mth, yr, argMd=5, function=MDY, format=date11., macarray=Y); +%put %do_over(mthyr); + +%zipArrays(mth, yr, argMd=5, function=MDY, format=date11., macarray=Y, reuse=cp); +%put %do_over(mthyr); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +--- + +## >>> `%sortMacroArray()` macro: <<< ####################### + +The sortMacroArray() macro +allow to sort elements of a macro array. + +The **limitation** is that sorted values are limited to 32767 bytes of length. + +See examples below for the details. + +### SYNTAX: ################################################################### + +The basic syntax is the following, the `<...>` means optional parameters: +~~~~~~~~~~~~~~~~~~~~~~~sas +%sortMacroArray( + array + <,valLength=> + <,outSet=> + <,sortseq=> +) +~~~~~~~~~~~~~~~~~~~~~~~ + +**Arguments description**: + +1. `array` - *Required*, name of an array generated by the `%array()` macro. + +* `valLength = 32767` - *Optional*, default value is `32767`, + maximum length of a variable storing macrovariable data. + (the reason of 32767 limitation) + +* `outSet = _NULL_` - *Optional*, default value is `_NULL_`, + an optional output dataset name. + +* `sortseq =` - *Optional*, default value is `LINGUISTIC(NUMERIC_COLLATION = ON)`, + sorting options for use in an internal `Proc SORT`. + +### EXAMPLES AND USECASES: #################################################### + + +**EXAMPLE 1.** Basic use-case. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + +options mprint; +ods html; +ods listing close; + + +%array(hij [4:9] $ 512 ("C33" "B22" "A11" "A01" "A02" "X42"), macarray=Y) + +%put NOTE: %do_over(hij); + +%sortMacroArray(hij, valLength=3, outSet = A_NULL_(compress=char)) + +%put NOTE: %do_over(hij); + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 2.** Basic use-case. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + +options mprint; +ods html; +ods listing close; + + +%array(ds = sashelp.class, vars = name|NNN height|h, macarray=Y) +%array(ds = sashelp.cars, vars = model|, macarray=Y) + +%put NOTE: %do_over(NNN); +%put NOTE: %do_over(H); +%put NOTE: %do_over(model); + +%sortMacroArray(NNN, valLength=30, outSet = A_NULL_(compress=char)) +%sortMacroArray(H, valLength=32) +%sortMacroArray(model, valLength=120) + +%put NOTE: %do_over(NNN); +%put NOTE: %do_over(H); +%put NOTE: %do_over(model); + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +--- + +## License #################################################################### + +Copyright (c) Bartosz Jablonski, since January 2019 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +--- diff --git a/hist/1.1.1/macroarray.zip b/hist/1.1.1/macroarray.zip new file mode 100644 index 0000000000000000000000000000000000000000..6bb2437b9e537f9c4344ad6d9b739a2822208c93 GIT binary patch literal 52051 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 PK%C(-a8}CeD2N9DJ1tp5 literal 0 HcmV?d00001 diff --git a/macroarray.md b/macroarray.md index fdeb46d..ca8b22d 100644 --- a/macroarray.md +++ b/macroarray.md @@ -19,7 +19,7 @@ --- -# The macroArray package [ver. 1.0.6] ############################################### +# The macroArray package [ver. 1.1.1] ############################################### The **macroArray** package implements a macro array facility: - `%array()`, @@ -75,10 +75,10 @@ Package contains: Required SAS Components: *Base SAS Software* -*SAS package generated by generatePackage, version 20230905* +*SAS package generated by generatePackage, version 20230904* The SHA256 hash digest for package macroArray: -`F*4FAAEE7DF2854EA31933AE017A89C1615C7291A66A07CCE345041EB0D587ED4E` +`F*E9C0C58FB36AC40C76A518066B8C6F9942202A9DB2C2D737E95D2BB6E4ECED50` --- # Content description ############################################################################################ diff --git a/macroarray.zip b/macroarray.zip index 411c831f9af6d0d2ede276746f281b6e17a0bff6..6bb2437b9e537f9c4344ad6d9b739a2822208c93 100644 GIT binary patch delta 17186 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

N{o{+#Lz#-(4}9`UEZn^~SQ@+!f+btq(5_ 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 delta 16966 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 G_kRFe>)0y*