From 5c4ff371bfc3a46dc3f0eb2e46d85ce93f878ec4 Mon Sep 17 00:00:00 2001 From: Bart Jablonski Date: Mon, 4 Sep 2023 16:32:03 +0200 Subject: [PATCH] The macroArray package [ver. 1.0.6] The macroArray package [ver. 1.0.6] Package regenerated with the latest version of the SAS Packages Framework (20230904). SHA256 digest for the latest version of `macroArray`: F*4FAAEE7DF2854EA31933AE017A89C1615C7291A66A07CCE345041EB0D587ED4E --- README.md | 2 +- hist/1.0.6/macroarray.md | 2199 +++++++++++++++++++++++++++++++++++++ hist/1.0.6/macroarray.zip | Bin 0 -> 51548 bytes macroarray.md | 6 +- macroarray.zip | Bin 51402 -> 51548 bytes 5 files changed, 2203 insertions(+), 4 deletions(-) create mode 100644 hist/1.0.6/macroarray.md create mode 100644 hist/1.0.6/macroarray.zip diff --git a/README.md b/README.md index f551d05..c8b5587 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*85E3BE4D163AC5223B6EC9D3C25C46564A656E3830998B4555A963180D767160 +SHA256 digest for the latest version of `macroArray`: F*4FAAEE7DF2854EA31933AE017A89C1615C7291A66A07CCE345041EB0D587ED4E [**Documentation for macroArray**](./macroarray.md "Documentation for macroArray") diff --git a/hist/1.0.6/macroarray.md b/hist/1.0.6/macroarray.md new file mode 100644 index 0000000..7f2e20e --- /dev/null +++ b/hist/1.0.6/macroarray.md @@ -0,0 +1,2199 @@ +- [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.0.6] ############################################### + +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 20230905* + +The SHA256 hash digest for package macroArray: +`F*4FAAEE7DF2854EA31933AE017A89C1615C7291A66A07CCE345041EB0D587ED4E` + +--- +# 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=> +) +~~~~~~~~~~~~~~~~~~~~~~~ + +**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 macro named with 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", + + + + +### EXAMPLES AND USECASES: #################################################### + + +**EXAMPLE 1.** Basic use-case. + Creating macroarray like in the array statement; + values are used by default; + different types of brackets are allowed; + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(a[*] x1-x5 (1:5)) + + %array(b{5} (5*17)) + + %* 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.)) + %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.** "Uppercas Letters" + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(UL[26] $, function = byte(rank("A")+_I_-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|) + %put _user_; + + %array(ds = sashelp.class, vars = height#hght weight weight|wght age|, macarray=Y) + %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) + %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.0.6/macroarray.zip b/hist/1.0.6/macroarray.zip new file mode 100644 index 0000000000000000000000000000000000000000..a047b7b0b5c812282db438e7258347e5bbe8706a GIT binary patch literal 51548 zcmaI7QjRlu;~pOCKzb z(Zlct45<_L03s(k@tPDCxVDuv^IJJOSv<;O={`v^40GT{W#!JriJt z{C*?ljw^F9ctf~Pq5lM{+DD^AdJJ&&{C+ilM4DVo&x>-SP}~3w-95A%?r2|ojm2h zf^1twuGhW(@nad%6NWCQmAjej#^rShc_l@=D18Vy`H@FQ&0ORU)JQOLOc{!8bC zo0HdOB_7eY#A5wxND|50Ih0ipA`apeuX3mwW{gULLGClBv`l=aWjDd@uj9Py2{ix)HVHCi&h~hGG}QL zk#&E0l&0`AN(ZSb2w#E6;{qySB1=BH57_H5uwQTXn zrgm*ANyVZxjy-92iUF>p_R8b3p4Zx_HJzl^!}HL4YHqC1+weyQ$&?H2fFmss>2O(YqJ$z_8^@Uo=)p}533=#qt} zK%C$m>;B@5oascdD2HtUD!Ph~8VTWyC}qn1hq}?ao!-dns5UVQ62ds+ZW?w08_G?P z-N%VygNTx27E=0uurlisC=Br#B;O?aB1q&H?!@(Jp*FT5bSnlD`%|Lg4bO{P3s;jk zivp39@8_H~JFao*Cz=dTWv2ir{Z^EOaC>6Uw58op;;frp+kz8iArC;@Gc zWoVpPa9w*Vt?$~I97i}i^_oG@Txw

+RS1f_pLndimSO){J#^=9>=Eg`pK4d|$Q2 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 literal 0 HcmV?d00001 diff --git a/macroarray.md b/macroarray.md index f1d823f..7f2e20e 100644 --- a/macroarray.md +++ b/macroarray.md @@ -19,7 +19,7 @@ --- -# The macroArray package [ver. 1.0.5] ############################################### +# The macroArray package [ver. 1.0.6] ############################################### 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 20230411* +*SAS package generated by generatePackage, version 20230905* The SHA256 hash digest for package macroArray: -`F*85E3BE4D163AC5223B6EC9D3C25C46564A656E3830998B4555A963180D767160` +`F*4FAAEE7DF2854EA31933AE017A89C1615C7291A66A07CCE345041EB0D587ED4E` --- # Content description ############################################################################################ diff --git a/macroarray.zip b/macroarray.zip index b9a9db58b7a601b645552af20a0681c3a4898a6a..a047b7b0b5c812282db438e7258347e5bbe8706a 100644 GIT binary patch delta 10439 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 KVAXp5X#X!I9BTXk delta 10245 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

DRn_^mvJC(T` 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 D*AytP