From 620ff4a74f4684ef014f45ed6eba1af8b957dbab Mon Sep 17 00:00:00 2001 From: Bart Jablonski Date: Wed, 6 Sep 2023 23:10:26 +0200 Subject: [PATCH] The macroArray package [ver. 1.1.0] The macroArray package [ver. 1.1.0] New parameter in the `%array()` macro: * `q=` - *Optional*, indicates (when set to `1`) if the value be surrounded by quotes. It uses `quote(cats(...))` combo under the hood. Default value is `0`. Ignored for `macarray=M`. --- README.md | 2 +- hist/1.1.0/macroarray.md | 2204 +++++++++++++++++++++++++++++++++++++ hist/1.1.0/macroarray.zip | Bin 0 -> 51814 bytes macroarray.md | 39 +- macroarray.zip | Bin 51548 -> 51814 bytes 5 files changed, 2227 insertions(+), 18 deletions(-) create mode 100644 hist/1.1.0/macroarray.md create mode 100644 hist/1.1.0/macroarray.zip diff --git a/README.md b/README.md index c8b5587..bd85c83 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*4FAAEE7DF2854EA31933AE017A89C1615C7291A66A07CCE345041EB0D587ED4E +SHA256 digest for the latest version of `macroArray`: F*6A22A01868F4203862B3685F543D723C7DB8E9AB3C1A6357D2BFA030971B0D3C [**Documentation for macroArray**](./macroarray.md "Documentation for macroArray") diff --git a/hist/1.1.0/macroarray.md b/hist/1.1.0/macroarray.md new file mode 100644 index 0000000..fdeb46d --- /dev/null +++ b/hist/1.1.0/macroarray.md @@ -0,0 +1,2204 @@ +- [The macroArray package](#macroarray) +- [Content description](#content-description) + * [`%appendArray()` macro](#appendarray-macro) + * [`%appendCell()` macro](#appendcell-macro) + * [`%array()` macro](#array-macro) + * [`%concatArrays()` macro](#concatarrays-macro) + * [`%deleteMacArray()` macro](#deletemacarray-macro) + * [`%do_over()` macro](#do-over-macro) + * [`%do_over2()` macro](#do-over2-macro) + * [`%do_over3()` macro](#do-over3-macro) + * [`%make_do_over()` macro](#make-do-over-macro) + * [`%mcHashTable()` macro](#mchashtable-macro) + * [`%mcDictionary()` macro](#mcdictionary-macro) + * [`%QzipArrays()` macro](#qziparrays-macro) + * [`%zipArrays()` macro](#ziparrays-macro) + * [`%sortMacroArray()` macro](#sortmacroarray-macro) + + * [License](#license) + +--- + +# The macroArray package [ver. 1.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=> + <,q=> +) +~~~~~~~~~~~~~~~~~~~~~~~ + +**Arguments description**: + +1. `array` - *Required*, an array name and a declaration/definition of an array,
+ e.g. `myArr[*] x1-x3 (4:6)`
+ or `myBrr[*] $ y1-y3 ("a" "b" "c")`
+ or `myCrr[3] $ ("d d d" "e,e,e" "f;f;f")`
+ or `myDrr p q r s`.
+ Macrovariables created by the macro are *global*. + If an array name is `_` (single underscore) then attached variables + list names are used, a call of the form: + `%array(_[*] p1 q2 r3 s4 (-1 -2 -3 -4))` + will create macrovariables: `p1`, `q2`, `r3`, and `s4` with respective + values: `-1`, `-2`, `-3`, and `-4`.
+ Three additional *global* macrovariables: + `LBOUND`, `HBOUND`, and `N` + are generated with the macroarray. See examples for more use-cases. + +* `function=` - *Optional*, a function or an expression to be applied to all array cells, + `_I_` is as array iterator, e.g. `_I_ + rand("uniform")`. + +* `before=` - *Optional*, a function or an expression to be added before looping through + array, e.g. `call streaminit(123)`. + +* `after=` - *Optional*, a function or an expression to be added after looping through + array, e.g. `call sortn(ABC)`. + +* `vnames=N` - *Optional*, default value `N`, if set to `Y`/`YES` then macroarray is built based + on variables names instead values, e.g. + `%array(myArr[*] x1-x3 (4:6), vnames=Y)` + will use `x1`, `x2`, and `x3` as values instead `4`, `5`, and `6`. + +* `macarray=N` - *Optional*, default value `N`, if set to `Y`/`YES` then a macro, named with the array + name, is compiled to create convenient envelope for multiple ampersands, e.g. + `%array(myArr[*] x1-x3 (4:6), macarray=Y)` + will create `%myArr(J)` macro which will allow to extract "data" + from macroarray like: + `%let x = %myArr(1);` + or when used with second parameter equal `I` (insert) allow to overwrite macroarrays + value: + `%let %myArr(17,i) = 42;` + If set to `M` then for a given array name the macro symbols table is scanned for + macrovariables with prefix like the array name and numeric suffixes, + then the minimum and the maximum index is determined + and all not existing global macrovariables are created and + a macro is generated in the same way as for the `Y` value. + +* `ds=` - *Optional*, use a dataset as a basis for a macroarray data, + if used by default overwrites use of the `array` parameter, honors `macarray=` + argument, dataset options are allowed, e.g. `sashelp.class(obs=5)` + +* `vars=` - *Optional*, a list of variables used to create macroarrays from a dataset, + the list format can be as follows (`<...>` means optional): + `variable1 <... variableN>` + delimiters are hash(`#`) and pipe(`|`), currently only space + is supported as separator, the meaning of `#` and `|` delimiters + will be explained in the following example: + if the `vars = height#h weight weight|w age|` value is provided + then the following macroarrays will be created:
+ 1) macroarray "H" with ALL(`#`) values of variable "height"
+ 2) macroarray "WEIGHT" with ALL(no separator is equivalent to #) + values of variable "weight"
+ 3) macroarray "W" with UNIQUE(|) values of variable "weight" and
+ 4) macroarray "AGE" with UNIQUE(|) values of variable "age". + +* `q=` - *Optional*, indicates (when set to `1`) if the value be surrounded by quotes. + It uses `quote(cats(...))` combo under the hood. Default value is `0`. + Ignored for `macarray=M`. + + +--- + +### EXAMPLES AND USECASES: #################################################### + + +**EXAMPLE 1.** Basic use-case. + Creating macroarray like in the array statement. + Values not variables names are used by default. + Different types of brackets are allowed. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(a[*] x1-x5 (1:5)) + + %array(b{5} (5*17), q=1) + + %* Mind the $ since it is a character array!; + %array(c(3) $ 10 ("a A" "b,B" "c;C")) + + %array(d x1-x5 (5 4 3 2 1)) + %put _user_; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 2.** Index ranges. + If range starts < 0 then it is shifted to 0. + In case when range is from `1` to `M` + then macrovariable `N` is set to `M` + In case when range is different + the `N` returns number of + elements in the array `(Hbound - Lbound + 1)`. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(d[-2:2] $ ("a" "b" "c" "d" "e")) + %put &=dLBOUND. &=dHBOUND. &=dN.; + %put &=d0. &=d1. &=d2. &=d3. &=d4.; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 3.** Functions. + It is possible to assign value of a function + or an expression to a cell of the array, + e.g. `array[_I_] = function(...)`. + You can use an iterator in a function. + As in case of usual arrays it is `_I_`. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(e[-3:3] $, function = "A" ) + %put &=eLBOUND. &=eHBOUND. &=eN.; + %put &=e0. &=e1. &=e2. &=e3. &=e4. &=e5. &=e6.; + + %array(f[-3:3], function = (2**_I_) ) + %put &=fLBOUND. &=fHBOUND. &=fN.; + %put &=f0. &=f1. &=f2. &=f3. &=f4. &=f5. &=f6.; + + %array(g[0:2], function = ranuni(123) ) + %put &=gLBOUND. &=gHBOUND. &=gN.; + %put &=g0. &=g1. &=g2.; + + %* Or something more complex; + %array(gg[0:11] $ 11, function = put(intnx("MONTH", '1jun2018'd, _I_, "E"), yymmn.), q=1) + %put &=ggLBOUND. &=ggHBOUND. &=ggN.; + %put &=gg0 &=gg1 &=gg2 ... &=gg11; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 4.** Functions cont. + If there is need for set-up something *before* or *after*: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(h[10:12] + ,function = rand('Uniform') + ,before = call streaminit(123) + ,after = call sortn(of h[*]) + ) + %put &=h10. &=h11. &=h12.; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 5.** Fibonacci series. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(i[1:10] (10*0) + ,function = ifn(_I_ < 2, 1, sum(i[max(_I_-2,1)], i[max(_I_-1,2)]) ) ) + %put &=i1 &=i2 &=i3 &=i4 &=i5 &=i6 &=i7 &=i8 &=i9 &=i10; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 6a.** Quoted "Uppercas Letters" + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(UL[26] $, function = byte(rank("A")+_I_-1) , q=1) + %put &=UL1 &=UL2 ... &=UL25 &=UL26; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 6b.** "Lowercase Letters" + Extended by `macarray=Y` option and + the input mode support (with `I`). + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(ll[26] $, function = byte(rank("a")+_I_-1), macarray=Y) + %put *%ll(&llLBOUND.)*%ll(3)*%ll(4)*%ll(5)*...*%ll(25)*%ll(&llHBOUND.)*; + + %* The range handling, warning; + %put *%ll(265)*; + + %* The input mode; + %put *before:*%ll(2)*; + %let %ll(2,I) = bbbbb; + %put *after: *%ll(2)*; + + %* The range handling, error; + %let %ll(265,I) = bbb; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 7.** The use of `vnames=Y` + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(R R1978-R1982) + %put &=R1 &=R2 &=R3 &=R4 &=R5; + + %array(R R1978-R1982 (78:82)) + %put &=R1 &=R2 &=R3 &=R4 &=R5; + + %array(R R1978-R1982 (78:82), vnames=Y) + %put &=R1 &=R2 &=R3 &=R4 &=R5; + + %array(R R1978-R1982, vnames=Y) + %put &=R1 &=R2 &=R3 &=R4 &=R5; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 8.** A "no name" array i.e. the `_[*]` array + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(_[*] x1-x5 (1:5)) + %put _user_; + + %array(_[*] p q r s (4*42)) + %put _user_; + + %* If no variables names than use _1 _2 ... _N; + %array(_[4] (-1 -2 -3 -4)) + %put &=_1 &=_2 &=_3 &=_4; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 9.** Pure macro code can be used in a data step. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + data test1; + set sashelp.class; + %array(ds[*] d1-d4 (4*17)) + a1 = &ds1.; + a2 = &ds2.; + a3 = &ds3.; + a4 = &ds4.; + run; + + data test2; + set sashelp.class; + %array(_[*] j k l m (4*17)) + a1 = &j.; + a2 = &k.; + a3 = &l.; + a4 = &m.; + run; + + data test3; + set sashelp.class; + %array(alpha[*] j k l m (101 102 103 104), macarray=Y) + a1 = %alpha(1); + a2 = %alpha(2); + a3 = %alpha(3); + a4 = %alpha(4); + a5 = %alpha(555); + run; + + data test4; + set sashelp.class; + %array(beta[*] j k l m (101 102 103 104), vnames=Y, macarray=Y) + a1 = "%beta(1)"; + a2 = "%beta(2)"; + a3 = "%beta(3)"; + a4 = "%beta(4)"; + a5 = "%beta(555)"; + run; + + data test5; + set sashelp.class; + %array(gamma[4] $ 12 ("101" "102" "103" "104"), macarray=Y) + a1 = "%gamma(1)"; + a2 = "%gamma(2)"; + a3 = "%gamma(3)"; + a4 = "%gamma(4)"; + a5 = "%gamma(555)"; + run; + + data test6; + set sashelp.class; + %array(ds = sashelp.cars, vars = Cylinders|, macarray=Y) + a0 = %Cylinders(0); + a1 = %Cylinders(1); + a2 = %Cylinders(2); + a3 = %Cylinders(3); + a4 = %Cylinders(4); + a5 = %Cylinders(555); + run; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 10.** Creating an array from a dataset, basic case. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(ds = sashelp.class, vars = height weight age) + %put _user_; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 11. Creating an array from a dataset, advanced. + If: `vars = height#h weight weight|w age|` + then create: + 1. macroarray "h" with ALL(#) values of variable "height" + 2. macroarray "weight" with ALL(no separator is equivalent to #) values of variable "weight" + 3. macroarray "w" with UNIQUE(|) values of variable "weight" + 4. macroarray "age" with UNIQUE(|) values of variable "age" + Currently the only separator in VARS is a space. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(ds = sashelp.class, vars = height#h weight weight|w age|, q=1) + %put _user_; + + %array(ds = sashelp.class, vars = height#hght weight weight|wght age|, macarray=Y, q=1) + %put *%hght(&hghtLBOUND.)**%weight(2)**%wght(&wghtHBOUND.)**%age(3)*; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 12.** Creating an array from a dataset with dataset options + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(ds = sashelp.cars(obs=100 where=(Cylinders=6)), vars = Make| Type| Model, macarray=Y) + %put *%make(&makeLBOUND.)*%Model(2)*%Model(3)*%Model(4)*%type(&typeHBOUND.)*; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 13.** Creating an array and macro from existing list of macrovariables + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %let myTest3 = 13; + %let myTest6 = 16; + %let myTest9 = 19; + + %array(myTest, macarray=M, q=1) + %do_over(myTest, phrase = %nrstr(%put *&_I_.*%myTest(&_I_.)*;)) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +--- + + + +## >>> `%concatArrays()` macro: <<< ########### + +The `%concatArrays()` macro allows to concatenate +two macroarrays created by the `%array()` macro. + +By default values of the second macroarray are removed. + +Dimensions of the first macroarray are extended. + +The `%concatArrays()` macro executes like a pure macro code. + +### SYNTAX: ##################################################################### + +The basic syntax is the following, the `<...>` means optional parameters: +~~~~~~~~~~~~~~~~~~~~~~~sas +%concatArrays( + first + ,second + <,removeSecond=Y> +) +~~~~~~~~~~~~~~~~~~~~~~~ + +**Arguments description**: + +1. `first` - *Required*, a name of a macroarray created by the `%array()` macro. + +2. `second` - *Required*, a name of a macroarray created by the `%array()` macro. + +* `removeSecond=Y` - *Optional*, default value `Y`, if set to `Y` then + the second array is removed. + + + + +### EXAMPLES AND USECASES: #################################################### + +**EXAMPLE 1.** Concatenate macroarrays LL and MM. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(ll[2:4] $ 12, + function = quote(put(today() + 10*_I_, yymmdd10.)), + macarray=Y + ) + %array(mm[10:13] $ 12000, + function = quote(repeat("A",123*_I_)), + macarray=Y + ) + %put *%ll(2)*%ll(3)*%ll(4)*; + + %concatArrays(ll, mm); + %put *%ll(2)*%ll(3)*%ll(4)*%ll(5)*%ll(6)**%ll(7)*%ll(8)*; + + %put *%mm(10)**%mm(11)*%mm(12)*%mm(13)*; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 2.** Error handling. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %concatArrays(ll, ) + %concatArrays(, mm) + + %concatArrays(noExistA, noExistB) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +--- + + + +## >>> `%deleteMacArray()` macro: <<< ####### + +The `%deleteMacArray()` macro allows to delete +macroarrays created by the `%array()` macro. + +The `%deleteMacArray()` macro executes like a pure macro code. + +### SYNTAX: ##################################################################### + +The basic syntax is the following, the `<...>` means optional parameters: +~~~~~~~~~~~~~~~~~~~~~~~sas +%deleteMacArray( + arrs + <,macarray=N> +) +~~~~~~~~~~~~~~~~~~~~~~~ + +**Arguments description**: + +1. `arrs` - *Required*, a space separated list of manes + of macroarray created by the `%array()` macro. + +* `macarray=N` - *Optional*, indicator should a macro + associated with macroarray to be deleted? + If `Y` or `YES` then the associated macro is deleted. + + + + +## >>> `%do_over()` macro: <<< ###################### + +The code of the macro was inspired by +*Ted Clay's* and *David Katz's* macro `%do_over()`. + +The `%DO_OVER()` macro allows to iterate over macroarray created with +the `macarray=Y` parameter of the `%ARRAY()` macro. + +The `%do_over()` macro executes like a pure macro code. + +### SYNTAX: ##################################################################### + +The basic syntax is the following, the `<...>` means optional parameters: +~~~~~~~~~~~~~~~~~~~~~~~sas +%do_over( + array + <,phrase=%nrstr(%&array(&_I_.))> + <,between=%str( )> + <,which = > +) +~~~~~~~~~~~~~~~~~~~~~~~ + +**Arguments description**: + +1. `array` - *Required*, indicates a macroarray which metadata (Lbound, Hbouns) + are to be used to loop in the `%do_over()` + +* `phrase=` - *Optional*, Default value `%nrstr(%&array(&_I_.))`, + a statement to be called in each iteration + of the internal do_over's loop. Loop iterator is `_I_`, + if you want to use `_I_` or array name + [e.g. `%myArr(&_I_.)`] *enclose it* in the `%NRSTR()` + macro quoting function. + +* `between=` - *Optional*, default value `%str( )` (space), + a statement to be called in between each + iteration of the internal do_over loop. + If macroquoted (e.g. `%str( + )`) then the `%unquote()` + function is automatically applied. + +* `which=` - *Optional*, a _SPACE_ separated list of indexes which + should be used to iterate over selected macroarray. + Possible special characters are `H` and `L` which means + *high* and *low* bound of an array, list could be set with + colons(`:`) in form of `start:end:by` (*no spaces between!*), + if `by` is omitted the default is `1`. If possible use + `1:5` rather `1 2 3 4 5` since the firs works faster. + + + +### EXAMPLES AND USECASES: #################################################### + +**EXAMPLE 1.** Simple looping. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(beta[*] j k l m (101 102 103 104), vnames=Y, macarray=Y) + + %put #%do_over(beta)#; + + %put #%do_over(beta, phrase=%nrstr("%beta(&_I_.)"), between=%str(,))#; + + data test1; + %array(beta[*] j k l m (101 102 103 104), vnames=Y, macarray=Y) + %do_over(beta, phrase=%nrstr(a&_I_. = "%beta(&_I_.)";)) + put _all_; + run; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 2.** Multiple arrays looping. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(alpha[*] j k l m n, vnames=Y, macarray=Y) + %array( beta[5] $ , function = "a", macarray=Y) + %array(gamma[4] (101 102 103 104), macarray=Y) + + data test2; + call streaminit(123); + %do_over(beta + , phrase = %nrstr(%beta(&_I_.) = %gamma(&_I_.) * rand('Uniform'); output;) + , between = put _all_; + ); + put _all_; + run; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 3.** Multiple arrays looping, cont. + Create multiple datasets. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %do_over(beta + , phrase = %nrstr( + data %alpha(&_I_.)2; + call streaminit(123); + %beta(&_I_.)x = %gamma(&_I_.) * rand('Uniform'); + output; + run; + ) + ) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 4.** Multiple arrays looping, cont. + Create multiple datasets using a macro. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %macro doit(ds, var=a, val=1); + data &ds.; + call streaminit(123); + &var. = &val. * rand('Uniform'); + output; + run; + %mend doit; + + %do_over(beta + , phrase = %nrstr( + %DOIT(%alpha(&_I_.)1, var = %beta(&_I_.), val = %gamma(&_I_.)) + ) + ) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 5.** `%do_over()` inside `%array()` + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(test[*] x1-x12 (1:12), macarray=Y) + + %put **%test(1)**%test(12)**; + + %put #%do_over(test)#; + + %array(abc[*] x1-x12 (%do_over(test,phrase=%nrstr(%eval(100-%test(&_I_.))))), macarray=Y) + + %put **%abc(1)**%abc(12)**; + + %put #%do_over(abc)#; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 6.** Looping over array with *macroquoted* separator. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(alpha[11] (5:15), macarray=Y) + + %let x = %do_over(alpha + , phrase = %NRSTR(%alpha(&_I_.)) + , between= %str( + ) + ); + %put &=x.; + %put %sysevalf(&x.); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 7.** Working with the `WHICH=` optional parameter + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(test[*] x01-x12, vnames= Y, macarray=Y) + + %put #%do_over(test)#; + + %put #%do_over(test, which= 1 3 5)#; + + %put #%do_over(test, which= 1:5)#; + + %put #%do_over(test, which= 1:5:2 7 8)#; + + %put #%do_over(test, which= L:H l:h)#; + + %put #%do_over(test, which= L:3 10:h)#; + + %put #%do_over(test, which= L:H h:l:-1 13 14)#; + + %put #%do_over(test, which= %eval(1+1):%eval(5+1))#; + + %put #%do_over(test, which= L:H h:l:-1 13 14, between=%str(,))#; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +--- + + + +## >>> `%do_over2()` macro: <<< #################### + +The code of the macro was inspired by +*Ted Clay's* and *David Katz's* macro `%do_over()`. + +The `%DO_OVER2()` macro allows to iterate over *two* macroarray created with +the `macarray=Y` parameter of the `%ARRAY()` macro. + +The `%do_over2()` macro executes like a pure macro code. + +### SYNTAX: ##################################################################### + +The basic syntax is the following, the `<...>` means optional parameters: +~~~~~~~~~~~~~~~~~~~~~~~sas +%do_over2( + arrayI + ,arrayJ + <,phrase=%nrstr(%&arrayI(&_I_.) %&arrayJ(&_J_.))> + <,between=%str( )> +) +~~~~~~~~~~~~~~~~~~~~~~~ + +**Arguments description**: + +1. `arrayI` - Required, indicates the first macroarray which metadata (Lbound, Hbouns) + are to be used in the outer loop in the `%do_over2()` + +2. `arrayJ` - Required, indicates the second macroarray which metadata (Lbound, Hbouns) + are to be used in the inner loop in the `%do_over2()` + +* `phrase=` - *Optional*, default value `%nrstr(%&arrayI(&_I_.) %&arrayJ(&_J_.))`, + a statement to be called in each iteration + of the *inner* loop. The outer loop iterator is `_I_`, + the inner loop iterator is `_J_`, + if you want to use `_I_`, `_J_`, or arrays names + [e.g. `%myArr(&_I_.)`] *enclose them* in the `%NRSTR()` + macro quoting function. + +* `between=` - *Optional*, default value `%str( )` (space), + a statement to be called in between each + iteration of the internal do_over2 loop. + If macroquoted (e.g. `%str( + )`) then the `%unquote()` + function is automatically applied. + + + + +### EXAMPLES AND USECASES: #################################################### + +**EXAMPLE 1.** Looping over two arrays. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(alpha[*] j k l m n, vnames=Y, macarray=Y) + %array( beta[4] (101 102 103 104), macarray=Y) + + %put *%do_over2(alpha, beta + , phrase = %NRSTR((%alpha(&_I_.), %beta(&_J_))) + )*; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 2.** Looping over two arrays with a separator. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(alpha[11] (5:15), macarray=Y) + %array( beta[ 4] (101 102 103 104), macarray=Y) + + %let x = %do_over2(alpha, beta + , phrase = %NRSTR((%alpha(&_I_.) * %beta(&_J_))) + , between= + + ); + %put &=x.; + %put %sysevalf(&x.); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 3.** Looping over two arrays with *macroquoted* separator. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(alpha[11] (5:15), macarray=Y) + %array( beta[ 4] (101 102 103 104), macarray=Y) + + %let x = %do_over2(alpha, beta + , phrase = %NRSTR((%alpha(&_I_.) * %beta(&_J_))) + , between= %str( + ) + ); + %put &=x.; + %put %sysevalf(&x.); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +--- + + + +## >>> `%do_over3()` macro: <<< #################### + +The code of the macro was inspired by +*Ted Clay's* and *David Katz's* macro `%do_over()`. + +The `%DO_OVER3()` macro allows to iterate over *three* macroarray created with +the `macarray=Y` parameter of the `%ARRAY()` macro. + +The `%do_over3()` macro executes like a pure macro code. + +### SYNTAX: ##################################################################### + +The basic syntax is the following, the `<...>` means optional parameters: +~~~~~~~~~~~~~~~~~~~~~~~sas +%do_over2( + arrayI + ,arrayJ + ,arrayK + <,phrase=%nrstr(%&arrayI(&_I_.) %&arrayJ(&_J_.) %&arrayK(&_K_.))> + <,between=%str( )> +) +~~~~~~~~~~~~~~~~~~~~~~~ + +**Arguments description**: + +1. `arrayI` - *Required*, indicates the first macroarray which metadata (Lbound, Hbouns) + are to be used in the outer loop in the `%do_over3()` + +2. `arrayJ` - *Required*, indicates the second macroarray which metadata (Lbound, Hbouns) + are to be used in the inner loop in the `%do_over3()` + +3. `arrayK` - *Required*, indicates the third macroarray which metadata (Lbound, Hbouns) + are to be used in the inner loop in the `%do_over3()` + +* `phrase=` - *Optional*, default value `%nrstr(%&arrayI(&_I_.) %&arrayJ(&_J_.) %&arrayK(&_K_.))`, + a statement to be called in each iteration + of the *inner* loop. The *outer* loop iterator is `_I_`, + the *middle* loop iterator is `_J_`, the *inner* loop iterator is `_K_`, + if you want to use `_I_`, `_J_`, `_K_`, or arrays names + [e.g. `%myArr(&_I_.)`] *enclose them* in the `%NRSTR()` + macro quoting function. + +* `between=` - *Optional*, default value `%str( )` (space), + a statement to be called in between each + iteration of the internal do_over2 loop. + If macroquoted (e.g. `%str( + )`) then the `%unquote()` + function is automatically applied. + + + + +### EXAMPLES AND USECASES: #################################################### + +**EXAMPLE 1.** Looping over 3 macroarrays. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(a1_[2] (0 1), macarray=Y) + %array(a2_[2] (2 3), macarray=Y) + %array(a3_[2] (4 5), macarray=Y) + + %do_over3(a1_, a2_, a3_ + , phrase = %NRSTR(%put (%a1_(&_I_.), %a2_(&_J_), %a3_(&_K_));) + ) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**EXAMPLE 2.** Looping 3 times over a macroarray. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(a[0:2] (0 1 2), macarray=Y) + + %do_over3(a, a, a + , phrase = %NRSTR(%put (%a(&_I_.), %a(&_J_), %a(&_K_));) + ) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +--- + + + +## >>> `%make_do_over()` macro: <<< ########### + +The code of the macro was inspired by +*Ted Clay's* and *David Katz's* macro `%do_over()`. + +The `%make_do_over()` macro allows to generate +the `%DO_OVER()` macros. It works *only* for *n>3*! + +The `%make_do_over()` macro does *not* executes like a pure macro code. + +### SYNTAX: ##################################################################### + +The basic syntax is the following, the `<...>` means optional parameters: +~~~~~~~~~~~~~~~~~~~~~~~sas +%make_do_over( + size +) +~~~~~~~~~~~~~~~~~~~~~~~ + +**Arguments description**: + +1. `size` - *Required*, indicates the number of dimensions + (i.e. inner loops) of the `%DO_OVER()` macro. + + + + +### EXAMPLES AND USECASES: #################################################### + +**EXAMPLE 1.** Code of created "4-loop" `%DO_OVER4()` macro + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %macro do_over4( + arrayI1, + arrayI2, + arrayI3, + arrayI4, + phrase=%nrstr( + %&arrayI1(&_I1_.) + %&arrayI2(&_I2_.) + %&arrayI3(&_I3_.) + %&arrayI3(&_I4_.) + ), + between=%str( ) + ); + %local _I1_ _I2_ _I3_ _I4_; + %do _I1_ = &&&arrayI1.LBOUND %to &&&arrayI1.HBOUND; + %do _I2_ = &&&arrayI2.LBOUND %to &&&arrayI2.HBOUND; + %do _I3_ = &&&arrayI3.LBOUND %to &&&arrayI3.HBOUND; + %do _I4_ = &&&arrayI4.LBOUND %to &&&arrayI4.HBOUND; + %if not ( + &_I1_. = &&&arrayI1.LBOUND + AND &_I2_. = &&&arrayI2.LBOUND + AND &_I3_. = &&&arrayI3.LBOUND + AND &_I4_. = &&&arrayI4.LBOUND + ) + %then %do;%unquote(&between.)%end;%unquote(%unquote(&phrase.)) + %end; + %end; + %end; + %end; + %mend do_over4; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 2.** Create a "4-loop" `%DO_OVER4()` macro + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %make_do_over(4); + + %array(a1_[2] (0 1), macarray=Y) + + %do_over4(a1_, a1_, a1_, a1_ + , phrase = %NRSTR(%put (%a1_(&_I1_.), %a1_(&_I2_), %a1_(&_I3_), %a1_(&_I4_));) + ) + + %put *%do_over4(a1_, a1_, a1_, a1_ + , between = * + )*; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**EXAMPLE 3.** Create a "5-loop" `%DO_OVER5()` macro + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %make_do_over(5); + + %array(a1_[2] (0 1), macarray=Y) + + %do_over5(a1_, a1_, a1_, a1_, a1_ + , phrase = %NRSTR(%put (%a1_(&_I1_.), %a1_(&_I2_), %a1_(&_I3_), %a1_(&_I4_), %a1_(&_I5_));) + ) + + %put *%do_over5(a1_, a1_, a1_, a1_, a1_ + , between = * + )* + ; + + options nomprint; + data test2; + %do_over5(a1_, a1_, a1_, a1_, a1_ + , phrase = %NRSTR(x1 = %a1_(&_I1_.); x2 = %a1_(&_I2_); x3 = %a1_(&_I3_); x4 = %a1_(&_I4_); x5 = %a1_(&_I5_);) + , between = output; + ) + output; + run; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 4.** Create all from 6 to 10 "do_overs" + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(loop[6:10] (6:10), macarray=Y) + %do_over(loop + , phrase = %nrstr( + %make_do_over(%loop(&_I_.)) + ) + ); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +--- + +## >>> `%mcHashTable()` macro: <<< ####################### + +The `%mcHashTable()` macro provided in the package +is designed to facilitate the idea of a "macro hash table" +concept, i.e. *a list of macrovariables with common prefix +and suffixes generated as a hash digest* which allows +to use values other than integers as indexes. + +The `%mcHashTable()` macro allows to generate other macros +which behaves like hash tables or dictionaries. See examples below. + +The `%mcHashTable()` macro executes like a pure macro code. + +### SYNTAX: ################################################################### + +The basic syntax is the following, the `<...>` means optional parameters: +~~~~~~~~~~~~~~~~~~~~~~~sas +%mcHashTable( + H + <,METHOD> + <,HASH=> +) +~~~~~~~~~~~~~~~~~~~~~~~ + +**Arguments description**: + +1. `H` - *Required*, a hash table macro name and a declaration/definition, + e.g. `mcHashTable(HT)`. It names a macro which is generated by + the `%mcHashTable()` macro. Provided name cannot be empty + or an underscore (`_`). No longer than *16* characters. + +2. `METHOD` - *Optional*, if empty (or DECLARE or DCL) then the code of + a macro hash table is compiled. + If `DELETE` then the macro hash table named by `H` and all + macrovariables named like "`&H._`" are deleted. + +* `HASH=` - *Optional*, indicates which hashing algorithms should be used, + available values are `CRC32` or `MD5`, the `CRC32` is the default. + +--- + +### THE CREATED MACRO `%&H.()`: #################################################### + +The created macro imitates behaviour of a hash table or a dictionary. +It is *not* dedicated for "long-ish" lists (above 1000 elements) since +the performance may be poor. + +The basic syntax is the following, the `<...>` means optional parameters: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%&H.( + METHOD + <,KEY=> + <,DATA=> +) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Arguments description**: + +1. `METHOD` - *Required*, indicate what behaviour should be executed. + Allowed values are: + - `ADD`, adds key and data portion to the macro hash table, + *multiple data portions* are available for one key. + - `FIND`, tests if given key exists in the macro hash table + and, if yes, returns data value associated with the key. + For multiple data portions see the `data=` parameter. + - `DP` (data portion) or `CHECK`, returns the number of data + portions for a given key. + - `CLEAR` removes all data and keys values. + - `KEYIDX`, allows to get data by the key index rather than value. + - `KEYVAL`, returns key value for a given key index. + - `CHECKIDX`, returns the number of data portions for + a given key index. + +* `KEY=` - *Optional*, provides key value for `ADD`, `FIND`,`DP`, `CHECK` + `CHECKIDX`, `KEYIDX`, and `KEYVAL` methods. Leading and trimming + spaces are removed from the value. + The `hashing(CRC32,...)` function or the `MD5(...)` function is + used to generate the hash. + +* `DATA=` - *Optional*, provides data value for the `ADD` method and + for the`FIND` method provides data portion number to be + extracted. Default value is `1` (used by the `FIND` method). + + +When macro is executed and when data are added the following types of +*global* macrovariables are created: +- `&H._########`, +- `&H._########_Xk`, +- `&H._########_Xi`, +- `&H._########_Xi_j`, +- `&H._KEYNUM`, +- and `&H._KEY_i`. + +The `#` represents value generated by the `hashing(CRC32,...)` function +or the `MD5(...)` function for the given key. + +The first type keeps information about possible collision for the key. + +The second type keeps information about value of a given key, +the `X` keeps the track of other colliding keys. + +The third type keeps information about number of data portions +for given key, the `X` keeps the track of other colliding keys. + +The fourth type keeps the data portion, the `j` indicates data portion number. + +The fifth type keeps the number of unique values of the key. + +The sixth type keeps the list of unique values of the key, +the `i` indicates key number. + +See examples below to see use cases. + +--- + +### EXAMPLES AND USECASES: #################################################### + + +**EXAMPLE 1.** Basic use-case. + Creating macro hash table, macro `HT` is generated. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%mcHashTable(HT) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Add elements to the `HT`. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%HT(ADD,key=x,data=17) +%HT(ADD,key=y,data=42) +%HT(ADD,key=z,data=303) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Add some duplicates for the key x. + See macrovariables created. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%HT(ADD,key=x,data=18) +%HT(ADD,key=x,data=19) + +%put _user_; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Check the number od data portions in macrohash + for the key `x` and non existing key `t`. +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%put ##%HT(DP,key=x)##; +%put ##%HT(DP,key=t)##; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Check the number od data portions in macrohash + for the key index 1 and 4. +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%put ##%HT(CHECKIDX,key=1)##; +%put ##%HT(CHECKIDX,key=4)##; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Prints first data values for various keys. + Key `t` does not exist in the macrohash. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%put #%HT(FIND,key=x)#; +%put #%HT(FIND,key=y)#; +%put #%HT(FIND,key=z)#; +%put #%HT(FIND,key=t)#; + +%put #%HT(FIND,key=x,data=2)#; +%put #%HT(FIND,key=x,data=3)#; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Print first and subsequent data values + for a given KeyIDX. Index `4` does not exist. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%put #%HT(KEYIDX,key=1)#; +%put #%HT(KEYIDX,key=2)#; +%put #%HT(KEYIDX,key=3)#; +%put #%HT(KEYIDX,key=4)#; + +%put #%HT(KEYIDX,key=1,data=2)#; +%put #%HT(KEYIDX,key=1,data=3)#; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Print the key values for a given KeyIDX. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%put #%HT(KEYVAL,key=1)#; +%put #%HT(KEYVAL,key=2)#; +%put #%HT(KEYVAL,key=3)#; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Clear and delete macro hash table `HT`. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%HT(CLEAR) +%mcHashTable(HT,DELETE) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 2.** Combine `CHECK` and `FIND` methods + with macros `%array()` and `%do_over()` + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%mcHashTable(H) +%H(ADD,key=x,data=17) +%H(ADD,key=x,data=18) +%H(ADD,key=x,data=19) + +%array(A[%H(CHECK,key=x)]); + +%put %do_over(A, phrase=%nrstr( + %H(FIND,key=x,data=&_i_) +), between = %str(,)); + +%mcHashTable(H,delete) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 3.** Populate macro hash table from a dataset. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%mcHashTable(CLASS) +%let t = %sysfunc(datetime()); +data _null_; + set sashelp.class; + call execute('%CLASS(ADD,key=' !! name !! ',data=' !! age !! ')'); + call execute('%CLASS(ADD,key=' !! name !! ',data=' !! weight !! ')'); + call execute('%CLASS(ADD,key=' !! name !! ',data=' !! height !! ')'); +run; +%put t = %sysevalf(%sysfunc(datetime()) - &t.); +%put _user_; +%CLASS(CLEAR) + + +%mcHashTable(CARS) +%let t = %sysfunc(datetime()); +data _null_; + set sashelp.cars; + call execute('%CARS(ADD,key=' !! catx("|",make,model) !! ',data=' !! MPG_CITY !! ')'); +run; +%put t = %sysevalf(%sysfunc(datetime()) - &t.); +%* %put _user_; +%CARS(CLEAR) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 4.** Data portion may require quoting and un-quoting.. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%mcHashTable(CODE) +%CODE(CLEAR) +%CODE(ADD,key=data, data=%str(data test; x = 42; run;)) +%CODE(ADD,key=proc, data=%str(proc print; run;)) +%CODE(ADD,key=macro,data=%nrstr(%put *****;)) + +%CODE(FIND,key=data) +%CODE(FIND,key=proc) +%unquote(%CODE(FIND,key=macro)) + +%mcHashTable(CODE,DELETE) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 5.** Longer lists. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%let size = 1000; + +%mcHashTable(AAA) +%mcHashTable(BBB) +%mcHashTable(CCC) +%mcHashTable(DDD) + +%let t = %sysfunc(datetime()); +data _null_; + do i = 1 to &size.; + call execute(cats('%AAA(ADD,key=A', i, ',data=', i, ')')); + end; +run; +%put t = %sysevalf(%sysfunc(datetime()) - &t.); +%put &=AAA_KEYSNUM; +%AAA(CLEAR) + +%let t = %sysfunc(datetime()); +data _null_; + do i = 1 to &size.; + call execute(cats('%BBB(ADD,key=B', i, ',data=', i, ')')); + call execute(cats('%BBB(ADD,key=B', i, ',data=', i+1, ')')); + end; +run; +%put t = %sysevalf(%sysfunc(datetime()) - &t.); +%put &=BBB_KEYSNUM; +%BBB(CLEAR) + +%let t = %sysfunc(datetime()); +data _null_; + t= datetime(); + do i = 1 to &size.; + call execute(cats('%CCC(ADD,key=C', i, ',data=', i, ')')); + end; + t = datetime() - t; + put t=; + t= datetime(); + do i = 1 to &size.; + call execute(cats('%CCC(ADD,key=C', i, ',data=', i+1, ')')); + end; + t = datetime() - t; + put t=; +run; +%put t = %sysevalf(%sysfunc(datetime()) - &t.); + +%let t = %sysfunc(datetime()); +data test; + do i = 1 to &size.; + x = resolve(cats('%CCC(FIND,key=C', i, ',data=1)')); + y = resolve(cats('%CCC(FIND,key=C', i, ',data=2)')); + output; + end; +run; +%put t = %sysevalf(%sysfunc(datetime()) - &t.); +%put &=CCC_KEYSNUM; +%CCC(CLEAR) + +%let t = %sysfunc(datetime()); +data _null_; + do i = 1 to &size.; + call execute(cats('%DDD(ADD,key=D,data=', i, ')')); + end; +run; +%put t = %sysevalf(%sysfunc(datetime()) - &t.); +%put &=DDD_KEYSNUM; +%put %DDD(CHECK,key=D); +%DDD(CLEAR) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 6.** Forbidden names. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%mcHashTable() +%mcHashTable(_) + +%mcHashTable(ABCDEFGHIJKLMNOPQ) %* bad; +%mcHashTable(ABCDEFGHIJKLMNOP) %* good; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**EXAMPLE 7.** Hashing algorithms. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%mcHashTable(H1,DCL,HASH=MD5) +%mcHashTable(H2,DECLARE,HASH=CRC32) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +--- + +## >>> `%mcDictionary()` macro: <<< ####################### + +The `%mcDictionary()` macro provided in the package +is designed to facilitate the idea of a "macro dictionary" +concept, i.e. *a list of macrovariables with common prefix +and suffixes generated as a hash digest* which allows +to use values other than integers as indexes. + +The `%mcDictionary()` macro allows to generate other macros +which behaves like a dictionary. See examples below. + +The `%mcDictionary()` macro executes like a pure macro code. + +### SYNTAX: ################################################################### + +The basic syntax is the following, the `<...>` means optional parameters: +~~~~~~~~~~~~~~~~~~~~~~~sas +%mcDictionary( + H + <,METHOD> +) +~~~~~~~~~~~~~~~~~~~~~~~ + +**Arguments description**: + +1. `H` - *Required*, a dictionary macro name and a declaration/definition, + e.g. `mcDictionary(HT)`. It names a macro which is generated by + the `%mcDictionary()` macro. Provided name cannot be empty + or an underscore (`_`). No longer than *16* characters. + +2. `METHOD` - *Optional*, if empty (or DECLARE or DCL) then the code of + a macro dictionary is compiled. + If `DELETE` then the macro dictionary named by `H` and all + macrovariables named like "`&H._`" are deleted. + +--- + +### THE CREATED MACRO `%&H.()`: #################################################### + +The created macro imitates behaviour of a dictionary. + +The basic syntax is the following, the `<...>` means optional parameters: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%&H.( + METHOD + <,KEY=> + <,DATA=> +) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Arguments description**: + +1. `METHOD` - *Required*, indicate what behaviour should be executed. + Allowed values are: + - `ADD`, adds key and data portion to the macro dictionary, + *multiple data portions* are NOT available for one key. + - `FIND`, tests if given key exists in the macro dictionary + and, if yes, returns data value associated with the key. + For multiple data portions see the `data=` parameter. + - `CHECK`, returns indicator if the key exists in dictionary. + - `DEL`, removes key and data portion from the macro dictionary. + - `LIST`, prints out a dictionary to the log. + - `CLEAR` removes all data and keys values. + +* `KEY=` - *Optional*, provides key value for `ADD`, `FIND`, `CHECK` + and `DEL` methods. + Leading and trimming spaces are removed from the value. + The `MD5(...)` function is used to generate the hash. + Default value is `_`. + +* `DATA=` - *Optional*, provides data value for the `ADD` method. + Default value is blank. + + +When macro is executed and when data are added the following types of +*global* macrovariables are created: +- `&H._########_K`, +- `&H._########_V`, +- `&H._KEYSNUM`. + +The `#` represents value generated by the `MD5(...)` function for the given key. + +The first type keeps information about the key. + +The second type keeps information about the value of a given key + +The third type keeps the number of unique values of the key. + +See examples below to see use cases. + +--- + +### EXAMPLES AND USECASES: #################################################### + + +**EXAMPLE 1.** Basic use-case. + Creating macro dictionary, macro `Dict` is generated. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%mcDictionary(Dict) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Add elements to the `Dict`. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%Dict(ADD,key=x,data=17) +%Dict(ADD,key=y y,data=42) +%Dict(ADD,key=z z z,data=303) + +%put _user_; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Add some duplicates for the key x. + See macrovariables created. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%Dict(ADD,key=x,data=18) + +%put _user_; + +%Dict(ADD,key=x,data=19) + +%put _user_; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Check for the key `x` and non existing key `t`. +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%put ##%Dict(CHECK,key=x)##; +%put ##%Dict(CHECK,key=t)##; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Prints data values for various keys. + Key `t` does not exist in the macrodictionary. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%put #%Dict(FIND,key=x)#; +%put #%Dict(FIND,key=y y)#; +%put #%Dict(FIND,key=z z z)#; +%put #%Dict(FIND,key=t)#; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + List dictionary content to the log. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%Dict(LIST); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Delete keys. + Key `t` does not exist in the macrodictionary. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%put #%Dict(DEL,key=z z z)#; +%put _user_; +%put #%Dict(DEL,key=t)#; +%put _user_; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Clear and delete macro dictionary `Dict`. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%Dict(CLEAR) +%put _user_; + +%mcDictionary(Dict,DELETE) +%put _user_; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 2.** Populate macro dictionary from a dataset. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%mcDictionary(CLASS) +%let t = %sysfunc(datetime()); +data _null_; + set sashelp.class; + call execute('%CLASS(ADD,key=' !! name !! ',data=' !! age !! ')'); +run; +%put t = %sysevalf(%sysfunc(datetime()) - &t.); +%put _user_; +%CLASS(CLEAR) + + +%mcDictionary(CARS) +%let t = %sysfunc(datetime()); +data _null_; + set sashelp.cars; + call execute('%CARS(ADD,key=' !! catx("|",make,model,type) !! ',data=' !! MPG_CITY !! ')'); +run; +%put t = %sysevalf(%sysfunc(datetime()) - &t.); +%put &=CARS_KEYSNUM.; +%CARS(LIST); +%CARS(CLEAR) +%put &=CARS_KEYSNUM.; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 3.** Data portion may require quoting and un-quoting.. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%mcDictionary(CODE) +%CODE(CLEAR) +%CODE(ADD,key=data, data=%str(data test; x = 42; run;)) +%CODE(ADD,key=proc, data=%str(proc print; run;)) +%CODE(ADD,key=macro,data=%nrstr(%put *****;)) + +%CODE(FIND,key=data) +%CODE(FIND,key=proc) +%unquote(%CODE(FIND,key=macro)) + +%CODE(LIST); + +%mcDictionary(CODE,DELETE) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 4.** Longer lists. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%let size = 1000; + +%mcDictionary(AAA) + +%let t = %sysfunc(datetime()); +data _null_; + do i = 1 to &size.; + call execute(cats('%AAA(ADD,key=A', i, ',data=', i, ')')); + end; +run; +%put t = %sysevalf(%sysfunc(datetime()) - &t.); +%put &=AAA_KEYSNUM; +%AAA(CLEAR) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 5.** Forbidden names. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%mcDictionary() +%mcDictionary(_) + +%mcDictionary(ABCDEFGHIJKLMNOPQ) %* bad; +%mcDictionary(ABCDEFGHIJKLMNOP) %* good; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +--- + +## >>> `%QzipArrays()` macro: <<< ####################### + +The zipArrays() and QzipArrays() macros +allow to use a function on elements of pair of +macro arrays. + +For two macroarrays the corresponding +elements are taken and the macro applies a function, provided by user, +to calculate result of the function on taken elements. + +When one of the arrays is shorter then elements are, by default, +"reused" starting from the beginning. But this behaviour can be altered. +See examples for the details. + +By default newly created macroarray name is concatenation +of first 13 characters of names of arrays used to create the new one, +e.g. if arrays names are `abc` and `def` then the result name is `abcdef`, +if arrays names are `abcd1234567890` and `efgh1234567890` then the result +name is `abcd123456789efgh123456789` + +The `zipArrays()` returns unquoted value [by `%unquote()`]. +The `QzipArrays()` returns quoted value [by `%superq()`]. + +See examples below for the details. + +The `%QzipArrays()` macro executes like a pure macro code. + +### SYNTAX: ################################################################### + +The basic syntax is the following, the `<...>` means optional parameters: +~~~~~~~~~~~~~~~~~~~~~~~sas +%QzipArrays( + first + ,second + <,function=> + <,operator=> + <,argBf=> + <,argMd=> + <,argAf=> + <,format=> + <,result=> + <,macarray=> + <,reuse=> +) +~~~~~~~~~~~~~~~~~~~~~~~ + +**Arguments description**: + +1. `first` - *Required*, a space separated list of texts. + +2. `second` - *Required*, a space separated list of texts. + +* `function = cat` - *Optional*, default value is `cat`, + a function which will be applied + to corresponding pairs of elements of + the first and the second list. + +* `operator =` - *Optional*, default value is empty, + arithmetic infix operator used with elements + the first and the second list. The first + list is used on the left side of the operator + the second list is used on the right side + of the operator. + +* `argBf =` - *Optional*, default value is empty, + arguments of the function inserted + *before* elements the first list. + If multiple should be comma separated. + +* `argMd =` - *Optional*, default value is empty, + arguments of the function inserted + *between* elements the first list and + the second list. + If multiple should be comma separated. + +* `argAf =` - *Optional*, default value is empty, + arguments of the function inserted + *after* elements the second list. + If multiple should be comma separated. + +* `format=` - *Optional*, default value is empty, + indicates a format which should be used + to format the result, does not work when + the `operator=` is used. + +* `result=` - *Optional*, default value is empty, + indicates a name of newly created macroarray, + by default created macroarray name is concatenation + of first 13 characters of names of arrays used + to create the new one. + +* `macarray=N` - *Optional*, default value is `N`, + if set to `Y`/`YES` then a macro, named with + the array name, is compiled to create convenient + envelope for multiple ampersands, see the + `%array()` macro for details. + +* `reuse=Y` - *Optional*, default value is `Y`, + when one of the arrays is shorter then elements + are *reused* starting from the beginning. + If `CP` then function is executed on the *Cartesian + product* of arrays elements. Any other value will + cut the process with the end of the shorter array. + See examples for the details. + +### EXAMPLES AND USECASES: #################################################### + +See examples in `%zipArrays()` help for the details. + +--- + +## >>> `%zipArrays()` macro: <<< ####################### + +The zipArrays() and QzipArrays() macros +allow to use a function on elements of pair of +macro arrays. + +For two macroarrays the corresponding +elements are taken and the macro applies a function, provided by user, +to calculate result of the function on taken elements. + +When one of the arrays is shorter then elements are, by default, +"reused" starting from the beginning. But this behaviour can be altered. +See examples for the details. + +By default newly created macroarray name is concatenation +of first 13 characters of names of arrays used to create the new one, +e.g. if arrays names are `abc` and `def` then the result name is `abcdef`, +if arrays names are `abcd1234567890` and `efgh1234567890` then the result +name is `abcd123456789efgh123456789` + +The `zipArrays()` returns unquoted value [by `%unquote()`]. +The `QzipArrays()` returns quoted value [by `%superq()`]. + +See examples below for the details. + +The `%zipArrays()` macro executes like a pure macro code. + +### SYNTAX: ################################################################### + +The basic syntax is the following, the `<...>` means optional parameters: +~~~~~~~~~~~~~~~~~~~~~~~sas +%zipArrays( + first + ,second + <,function=> + <,operator=> + <,argBf=> + <,argMd=> + <,argAf=> + <,format=> + <,result=> + <,macarray=> + <,reuse=> +) +~~~~~~~~~~~~~~~~~~~~~~~ + +**Arguments description**: + +1. `first` - *Required*, a space separated list of texts. + +2. `second` - *Required*, a space separated list of texts. + +* `function = cat` - *Optional*, default value is `cat`, + a function which will be applied + to corresponding pairs of elements of + the first and the second list. + +* `operator =` - *Optional*, default value is empty, + arithmetic infix operator used with elements + the first and the second list. The first + list is used on the left side of the operator + the second list is used on the right side + of the operator. + +* `argBf =` - *Optional*, default value is empty, + arguments of the function inserted + *before* elements the first list. + If multiple should be comma separated. + +* `argMd =` - *Optional*, default value is empty, + arguments of the function inserted + *between* elements the first list and + the second list. + If multiple should be comma separated. + +* `argAf =` - *Optional*, default value is empty, + arguments of the function inserted + *after* elements the second list. + If multiple should be comma separated. + +* `format=` - *Optional*, default value is empty, + indicates a format which should be used + to format the result, does not work when + the `operator=` is used. + +* `result=` - *Optional*, default value is empty, + indicates a name of newly created macroarray, + by default created macroarray name is concatenation + of first 13 characters of names of arrays used + to create the new one. + +* `macarray=N` - *Optional*, default value is `N`, + if set to `Y`/`YES` then a macro, named with + the array name, is compiled to create convenient + envelope for multiple ampersands, see the + `%array()` macro for details. + +* `reuse=Y` - *Optional*, default value is `Y`, + when one of the arrays is shorter then elements + are *reused* starting from the beginning. + If `CP` then function is executed on the *Cartesian + product* of arrays elements. Any other value will + cut the process with the end of the shorter array. + See examples for the details. + +### EXAMPLES AND USECASES: #################################################### + +**EXAMPLE 1.** Simple concatenation of elements: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%array(a[*] x1-x3 (1:3)) +%array(b[*] x1-x5 (11:15)) + +%put _user_; + +%zipArrays(a, b); +%put _user_; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 2.** Shorter list is "reused": +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%array(a[6] (1:6)) +%array(b[3] (10 20 30)) + +%zipArrays(a, b, result=A_and_B, macarray=Y); +%put %do_over(A_and_B); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 3.** Use of the `operator=`: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%array(c[0:4] (000 100 200 300 400)) +%array(d[2:16] (1002:1016)) + +%zipArrays(c, d, operator=+, result=C_plus_D, macarray=Y); +%put (%do_over(C_plus_D)); + +%put %C_plus_D(1); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 4.** If one of array names is empty or an array does not exist: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%array(a[6] (1:6)) +%array(b[3] (10 20 30)) + +%zipArrays(a, ); +%zipArrays(, b); + +%zipArrays(a, z); +%zipArrays(z, b); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 5.** Use of the `function=`: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%array(one[3] A B C, vnames=Y) +%array(two[5] p q r s t, vnames=Y) + +%zipArrays( + one +,two +,function = catx +,argBf = %str( ) +,format = $quote. +,macarray=Y +) +%put %do_over(onetwo); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 6.** To reuse or not to reuse, or maybe Cartesian product: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%array(e[3] (10 20 30)) +%array(f[2] (5:6)) + +%zipArrays(e, f, reuse=n, operator=+, macarray=Y, result=_noReuse); +%zipArrays(e, f, reuse=y, operator=+, macarray=Y, result=_yesReuse); +%zipArrays(e, f, reuse=cp, operator=+, macarray=Y, result=_cartProdReuse); + +%put %do_over(_noReuse); +%put %do_over(_yesReuse); +%put %do_over(_cartProdReuse); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 7.** Use middle argument: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%array(yr[3] (2018:2020)) +%array(mth[12] (1:12)) + +%zipArrays(mth, yr, argMd=5, function=MDY, format=date11., macarray=Y); +%put %do_over(mthyr); + +%zipArrays(mth, yr, argMd=5, function=MDY, format=date11., macarray=Y, reuse=cp); +%put %do_over(mthyr); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +--- + +## >>> `%sortMacroArray()` macro: <<< ####################### + +The sortMacroArray() macro +allow to sort elements of a macro array. + +The **limitation** is that sorted values are limited to 32767 bytes of length. + +See examples below for the details. + +### SYNTAX: ################################################################### + +The basic syntax is the following, the `<...>` means optional parameters: +~~~~~~~~~~~~~~~~~~~~~~~sas +%sortMacroArray( + array + <,valLength=> + <,outSet=> + <,sortseq=> +) +~~~~~~~~~~~~~~~~~~~~~~~ + +**Arguments description**: + +1. `array` - *Required*, name of an array generated by the `%array()` macro. + +* `valLength = 32767` - *Optional*, default value is `32767`, + maximum length of a variable storing macrovariable data. + (the reason of 32767 limitation) + +* `outSet = _NULL_` - *Optional*, default value is `_NULL_`, + an optional output dataset name. + +* `sortseq =` - *Optional*, default value is `LINGUISTIC(NUMERIC_COLLATION = ON)`, + sorting options for use in an internal `Proc SORT`. + +### EXAMPLES AND USECASES: #################################################### + + +**EXAMPLE 1.** Basic use-case. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + +options mprint; +ods html; +ods listing close; + + +%array(hij [4:9] $ 512 ("C33" "B22" "A11" "A01" "A02" "X42"), macarray=Y) + +%put NOTE: %do_over(hij); + +%sortMacroArray(hij, valLength=3, outSet = A_NULL_(compress=char)) + +%put NOTE: %do_over(hij); + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 2.** Basic use-case. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + +options mprint; +ods html; +ods listing close; + + +%array(ds = sashelp.class, vars = name|NNN height|h, macarray=Y) +%array(ds = sashelp.cars, vars = model|, macarray=Y) + +%put NOTE: %do_over(NNN); +%put NOTE: %do_over(H); +%put NOTE: %do_over(model); + +%sortMacroArray(NNN, valLength=30, outSet = A_NULL_(compress=char)) +%sortMacroArray(H, valLength=32) +%sortMacroArray(model, valLength=120) + +%put NOTE: %do_over(NNN); +%put NOTE: %do_over(H); +%put NOTE: %do_over(model); + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +--- + +## License #################################################################### + +Copyright (c) Bartosz Jablonski, since January 2019 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +--- diff --git a/hist/1.1.0/macroarray.zip b/hist/1.1.0/macroarray.zip new file mode 100644 index 0000000000000000000000000000000000000000..411c831f9af6d0d2ede276746f281b6e17a0bff6 GIT binary patch literal 51814 zcmaI6Q>YN+rDQqH<^5s`Tq5`l9lz)>8`4-E(K{| z5EK9a00;omRx02BZdQ)go*O9vNAdpkO3LuWt$gnys@=hLEQ zYrn~c@M910mzf(=%~9K;>d+9MQ*0!4e~Ih{ZdJ&%y$=$%`a>R!9e zo#P&S=EHE~Vzt>k#TZg`k{#c9tM0MD_@+(>Goq`o5lB^hrNlD9RfYRfjodo zs<#Q{XU^QAkOjp-wQf_hOdlNsxqiyU{lm5p0eO5DEidYgat`0GsF_!_&td_KLMmP^ z3gIv3|NZ_ugw;HP?G16wY=%fS4?^a3vodAyso&uC?8cYgg$rL-Iyf0EJD0@r<<+WWyXXpwyt8LQe7c@eB-*E>m>hJmRP5J}>BKn+aR1Zt*b(O zG2^zpxY@Pl_xKUg9f&@wox6eT&gE?dWi3tDsACj1@t$i()l3%3c_;*>zOe4?@F{G| z!_{-m7T@qweZJ-`JfigVmBK0(2?zNS$nA=6UV9$fopQ`snO>9(-u8vtG@e`u{W>Cb zG!Lv_6^nfh#Ph^Y&RU3PWM(cp`nlPx;i8v*F=mUt61fLypeAurF57Oh0)^LX#AQ3n zHRYXkg;FW_ObN6g+SmMD0l!RX)A#--hsq8!s>h~#0|qOXw4C>gr4ja z(!y5Zt_hviw|>Vy2KPj~;_3@diJ#z4Jj~8>cf@-;#yYiL9Am zOSc*og+gfv$DynjbqD9UkHu+q^NmgHhJJi)@!-f3J0ms^e&7?6XxgD5+r)x8tVVLz z!|2O;bCCyDiP*B7x-OGswF3VGANDJVx~9+*Ke9=HUs8Se*fND@v?{2quK96!AL4N9 z3#b^>yL8e&{I2#~mUfy(sDnI{k~%=fE_mtX3M{7nS4g=4N!A0V@SfviEp!Q4*z`$8 z;8TEo6G2*x-1(@%1ShSYhRTXhnn}?VD22*%!FCS2Ri0>fV49&eqMR19PD)PUGLx;O z)#t%NLkJYq7IMnKR#}Zv6oy2MQXfjA5rqm1k8;XHveUYsTGfkbEs;@)ru)wADRUvj z#UY3buR~6{bsJPHLv704SEpD6ic;3QI&}*E1IEv4W(6nK;_K=YT;V^kCz8s^G6Dzy zK>Q#6K>x!Y8%twTJ7?4XhC8}S((xM%2tDEx{uquMDTUXED?2hqXsv{i+4adqk}!_g zMkZN>*LAlt2JW3He~4zMUNZ?>%FNB-d;>aP@J=Q`FMs>kTd=Rr{4+qhFtuYt@2j_% zeSY4~rE!K8OSb1d?5`k3gzIv4cnA9{7|-YeyBD#p@HX_?gXIV`6b_lQn;#+SJM*V3 zMt~_S6#3#DSf0iXulaP67df^AA9ntV5fZxm<;8!-P$B5=#%vDnoU=|}W*@rpQ#x

&iYG4S^@b5tL+03+xjL^Z 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 bD3p=I0B=^{(Ws#N48$2e181dTkAQdpk<#mb literal 0 HcmV?d00001 diff --git a/macroarray.md b/macroarray.md index 7f2e20e..fdeb46d 100644 --- a/macroarray.md +++ b/macroarray.md @@ -278,6 +278,7 @@ The basic syntax is the following, the `<...>` means optional parameters: <,macarray=N> <,ds=> <,vars=> + <,q=> ) ~~~~~~~~~~~~~~~~~~~~~~~ @@ -312,8 +313,8 @@ The basic syntax is the following, the `<...>` means optional parameters: `%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. +* `macarray=N` - *Optional*, default value `N`, if set to `Y`/`YES` then a macro, named with the array + name, is compiled to create convenient envelope for multiple ampersands, e.g. `%array(myArr[*] x1-x3 (4:6), macarray=Y)` will create `%myArr(J)` macro which will allow to extract "data" from macroarray like: @@ -325,8 +326,8 @@ The basic syntax is the following, the `<...>` means optional parameters: 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 - + 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)` @@ -343,23 +344,27 @@ The basic syntax is the following, the `<...>` means optional parameters: 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", - + 4) macroarray "AGE" with UNIQUE(|) values of variable "age". + +* `q=` - *Optional*, indicates (when set to `1`) if the value be surrounded by quotes. + It uses `quote(cats(...))` combo under the hood. Default value is `0`. + Ignored for `macarray=M`. +--- ### EXAMPLES AND USECASES: #################################################### **EXAMPLE 1.** Basic use-case. - Creating macroarray like in the array statement; - values are used by default; - different types of brackets are allowed; + Creating macroarray like in the array statement. + Values not variables names are used by default. + Different types of brackets are allowed. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas %array(a[*] x1-x5 (1:5)) - %array(b{5} (5*17)) + %array(b{5} (5*17), q=1) %* Mind the $ since it is a character array!; %array(c(3) $ 10 ("a A" "b,B" "c;C")) @@ -405,7 +410,7 @@ The basic syntax is the following, the `<...>` means optional parameters: %put &=g0. &=g1. &=g2.; %* Or something more complex; - %array(gg[0:11] $ 11, function = put(intnx("MONTH", '1jun2018'd, _I_, "E"), yymmn.)) + %array(gg[0:11] $ 11, function = put(intnx("MONTH", '1jun2018'd, _I_, "E"), yymmn.), q=1) %put &=ggLBOUND. &=ggHBOUND. &=ggN.; %put &=gg0 &=gg1 &=gg2 ... &=gg11; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -433,10 +438,10 @@ The basic syntax is the following, the `<...>` means optional parameters: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -**EXAMPLE 6a.** "Uppercas Letters" +**EXAMPLE 6a.** Quoted "Uppercas Letters" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas - %array(UL[26] $, function = byte(rank("A")+_I_-1) ) + %array(UL[26] $, function = byte(rank("A")+_I_-1) , q=1) %put &=UL1 &=UL2 ... &=UL25 &=UL26; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -451,7 +456,7 @@ The basic syntax is the following, the `<...>` means optional parameters: %* The range handling, warning; %put *%ll(265)*; - + %* The input mode; %put *before:*%ll(2)*; %let %ll(2,I) = bbbbb; @@ -576,10 +581,10 @@ The basic syntax is the following, the `<...>` means optional parameters: Currently the only separator in VARS is a space. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas - %array(ds = sashelp.class, vars = height#h weight weight|w age|) + %array(ds = sashelp.class, vars = height#h weight weight|w age|, q=1) %put _user_; - %array(ds = sashelp.class, vars = height#hght weight weight|wght age|, macarray=Y) + %array(ds = sashelp.class, vars = height#hght weight weight|wght age|, macarray=Y, q=1) %put *%hght(&hghtLBOUND.)**%weight(2)**%wght(&wghtHBOUND.)**%age(3)*; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -599,7 +604,7 @@ The basic syntax is the following, the `<...>` means optional parameters: %let myTest6 = 16; %let myTest9 = 19; - %array(myTest, macarray=M) + %array(myTest, macarray=M, q=1) %do_over(myTest, phrase = %nrstr(%put *&_I_.*%myTest(&_I_.)*;)) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/macroarray.zip b/macroarray.zip index a047b7b0b5c812282db438e7258347e5bbe8706a..411c831f9af6d0d2ede276746f281b6e17a0bff6 100644 GIT binary patch delta 16713 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%0AKC82Fdm`YuS6BnsRtxmSX|C%ochCPb*c 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 @>TjO`?NuMQ?JDR#e3jL@5`Jv?x{k!n*Oq-8g* zJm49cp;~t^pIDR>pn%;|n`G6y=23g{(gtCq=*Ezm-6@TN&lz9oR(W7vhx=2~>yfaN zJ~bK;2{YkXV>`rU9MkUvshUIH4+Xdcc3!jqwhq^&MvKHBg0@ypFM1l8u0d7y!-x|3 zFXA=cs#h-?dAkWa1Y^LP?>z)-IjX8iMiX)H*ru9L#xsd?6goqKyveTt9^(OXHkzSI z<^n*%nb&fH9V~M?gVwwxf+_idgXt9NuHz9m-me?m-zH{;X>>n#%!|R2wyXs5< zl@?^aVuWlcJIABpfwcgh{_wVP=%b`gkK&?hiEdOor3;bD* z2}KqZgBhBSkrJVi+f=C8w2TeqdnwFO4H{c&J6hYEYmsKRf#8xtJJF3v+nxzNZeH7* znM{~bfNmpt0@7fEl^A+IC?)&?WSjKGMFI4@;PXSr;yByj7@`+N#j2(RVKfu~A=p_1 z9j`%$3JdpoEjxIAM3!Ur$LG1hS0cfnxa`2oyBV++`%pk-`vD%E^^QuAAh~4g%r(fct!R`zatXb85=l!eJSQip8cz`w!Mv zySt~_m)C-5K;-hnmU5CvDjgeBIudyGRiQl`yAekYPf+UQGjGO-whq`v{oN8xV@4x< z!&%oPLLT2|Rr2M{5=7Dim&DclP?mV5vF3dh9FeTN2oZwh0QL{`llTEJReH1PF9(ez z)-JOlZ#VB?>yv4#E5{~pw+!gAqPLIqe#*6rPM�-$nf5;m-UuaCIjY|Mu&(g=Nrj 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 qQ=@p`71bcX*&0G1+}OW