From f1152a24dbf3b095c6a14a821a3fde00d55d8250 Mon Sep 17 00:00:00 2001 From: "Bart Jablonski (yabwon)" Date: Fri, 30 Sep 2022 18:49:29 +0200 Subject: [PATCH] The macroArray package [ver. 1.0] Initial commit of the package --- hist/1.0/macroarray.zip | Bin 0 -> 50321 bytes macroarray.md | 2199 +++++++++++++++++++++++++++++++++++++++ macroarray.zip | Bin 0 -> 50321 bytes 3 files changed, 2199 insertions(+) create mode 100644 hist/1.0/macroarray.zip create mode 100644 macroarray.md create mode 100644 macroarray.zip diff --git a/hist/1.0/macroarray.zip b/hist/1.0/macroarray.zip new file mode 100644 index 0000000000000000000000000000000000000000..54dc081dcf419362fd1a126a217793bd3c82aa97 GIT binary patch literal 50321 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 p8u~ZXpIqTTp ############################################### + +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 20220830.* + +The SHA256 hash digest for package macroArray: +`ED12BC96F8A4E9E7C4D651EC1E15479DB9B55D98B274B63C507ED842081F7AB7` + +--- +# 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/macroarray.zip b/macroarray.zip new file mode 100644 index 0000000000000000000000000000000000000000..54dc081dcf419362fd1a126a217793bd3c82aa97 GIT binary patch literal 50321 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 p8u~ZXpIqTTp