macroArray, version 0.7:

macroArray, version 0.7:

The `%mcHashTable()` macro was added in the package.
It 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.
This commit is contained in:
yabwon
2020-10-23 10:34:20 +02:00
parent 2730a9438f
commit 4eaa1e63ec
5 changed files with 379 additions and 18 deletions

View File

@@ -88,7 +88,7 @@ SHA256 digest for SQLinDS: 135DC50C0412B8CEAF6D5349B8A203C0ADB23D4F5C2680B6A35FD
SHA256 digest for DFA: E67A0863992722A5F535F56E14EF8D19A55F74FB374447BF11B5ED74029C29CB SHA256 digest for DFA: E67A0863992722A5F535F56E14EF8D19A55F74FB374447BF11B5ED74029C29CB
- **macroArray**\[0.6\], implementation of an array concept in a macrolanguage, e.g. - **macroArray**\[0.7\], implementation of an array concept in a macrolanguage, e.g.
``` ```
%array(ABC[17] (111:127), macarray=Y); %array(ABC[17] (111:127), macarray=Y);
@@ -107,7 +107,7 @@ SHA256 digest for DFA: E67A0863992722A5F535F56E14EF8D19A55F74FB374447BF11B5ED740
which = 1:H:2 which = 1:H:2
); );
``` ```
SHA256 digest for macroArray: 42771AA7CD2A0608E1EE25F104F21CCCC296919910E4BCA7AD9AE46A291BB8D7 SHA256 digest for macroArray: 75056F508E96296DC50096BBB054C58334DB913AD37885958099EDCE0C330CB2
[Documentation for macroArray](https://github.com/yabwon/SAS_PACKAGES/blob/master/packages/macroarray.md "Documentation for macroArray") [Documentation for macroArray](https://github.com/yabwon/SAS_PACKAGES/blob/master/packages/macroarray.md "Documentation for macroArray")

View File

@@ -55,7 +55,7 @@ SHA256 digest for DFA: E67A0863992722A5F535F56E14EF8D19A55F74FB374447BF11B5ED740
--- ---
- **macroArray**\[0.6\], implementation of an array concept in a macro language, e.g. - **macroArray**\[0.7\], implementation of an array concept in a macro language, e.g.
``` ```
%array(ABC[17] (111:127), macarray=Y); %array(ABC[17] (111:127), macarray=Y);
@@ -74,7 +74,7 @@ SHA256 digest for DFA: E67A0863992722A5F535F56E14EF8D19A55F74FB374447BF11B5ED740
which = 1:H:2 which = 1:H:2
); );
``` ```
SHA256 digest for macroArray: 42771AA7CD2A0608E1EE25F104F21CCCC296919910E4BCA7AD9AE46A291BB8D7 SHA256 digest for macroArray: 75056F508E96296DC50096BBB054C58334DB913AD37885958099EDCE0C330CB2
[Documentation for macroArray](https://github.com/yabwon/SAS_PACKAGES/blob/master/packages/macroarray.md "Documentation for macroArray") [Documentation for macroArray](https://github.com/yabwon/SAS_PACKAGES/blob/master/packages/macroarray.md "Documentation for macroArray")

View File

@@ -1,3 +1,6 @@
/* 20201023 */
macroArray: 75056F508E96296DC50096BBB054C58334DB913AD37885958099EDCE0C330CB2
/* 20201020 */ /* 20201020 */
BasePlus: 9549378E5F81DA4DC421C366DF006D270261852336CE3DCD88FF8E2A759938C8 BasePlus: 9549378E5F81DA4DC421C366DF006D270261852336CE3DCD88FF8E2A759938C8

View File

@@ -1,4 +1,4 @@
- [The macroArray package [ver. 0.6]](#macroarray) - [The macroArray package](#macroarray)
- [Content description](#content-description) - [Content description](#content-description)
* [`%appendArray()` macro](#appendarray-macro) * [`%appendArray()` macro](#appendarray-macro)
* [`%appendCell()` macro](#appendcell-macro) * [`%appendCell()` macro](#appendcell-macro)
@@ -9,11 +9,12 @@
* [`%do_over2()` macro](#do-over2-macro) * [`%do_over2()` macro](#do-over2-macro)
* [`%do_over3()` macro](#do-over3-macro) * [`%do_over3()` macro](#do-over3-macro)
* [`%make_do_over()` macro](#make-do-over-macro) * [`%make_do_over()` macro](#make-do-over-macro)
* [`%mcHashTable()` macro](#mchashtable-macro)
* [License](#license) * [License](#license)
--- ---
# The macroArray package [ver. 0.6] <a name="macroarray-package"></a> ############################################### # The macroArray package [ver. 0.7] <a name="macroarray-package"></a> ###############################################
The **macroArray** package implements a macro array facility: The **macroArray** package implements a macro array facility:
- `%array()`, - `%array()`,
@@ -21,7 +22,8 @@ The **macroArray** package implements a macro array facility:
- `%make_do_over()`, - `%make_do_over()`,
- `%deletemacarray()`, - `%deletemacarray()`,
- `%concatarrays()`, - `%concatarrays()`,
- `%appendcell()`. - `%appendcell()`,
- `%mcHashTable()`,
- etc. - etc.
The set of macros, which emulates classic The set of macros, which emulates classic
@@ -47,23 +49,24 @@ to verify the following options:
--- ---
Package contains: Package contains:
1. macro appendarray 1. macro appendarray
2. macro appendcell 2. macro appendcell
3. macro array 3. macro array
4. macro concatarrays 4. macro concatarrays
5. macro deletemacarray 5. macro deletemacarray
6. macro do_over 6. macro do_over
7. macro do_over2 7. macro do_over2
8. macro do_over3 8. macro do_over3
9. macro make_do_over 9. macro make_do_over
10. macro mchashtable
Required SAS Components: Required SAS Components:
*Base SAS Software* *Base SAS Software*
*SAS package generated by generatePackage, version 20200911* *SAS package generated by generatePackage, version 20201018.*
The SHA256 hash digest for package macroArray: The SHA256 hash digest for package macroArray:
`42771AA7CD2A0608E1EE25F104F21CCCC296919910E4BCA7AD9AE46A291BB8D7` `75056F508E96296DC50096BBB054C58334DB913AD37885958099EDCE0C330CB2`
--- ---
# Content description ############################################################################################ # Content description ############################################################################################
@@ -1161,6 +1164,361 @@ The basic syntax is the following, the `<...>` means optional parameters:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
--- ---
## >>> `%mcHashTable()` macro: <<< <a name="mchashtable-macro"></a> #######################
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 2.** 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 3.** 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 4.** 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 5.** Forbidden names.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
%mcHashTable()
%mcHashTable(_)
%mcHashTable(ABCDEFGHIJKLMNOPQ) %* bad;
%mcHashTable(ABCDEFGHIJKLMNOP) %* good;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
**EXAMPLE 5.** Hashing algorithms.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
%mcHashTable(H1,DCL,HASH=MD5)
%mcHashTable(H2,DECLARE,HASH=CRC32)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
---
## License #################################################################### ## License ####################################################################
Copyright (c) Bartosz Jablonski, since January 2019 Copyright (c) Bartosz Jablonski, since January 2019

Binary file not shown.