mirror of
https://github.com/sasjs/core.git
synced 2026-07-23 15:35:29 +00:00
Merge pull request #433 from sasjs/mp_rowhash
refactor mf_wordsinstr1andstr2 + mf_wordsinstr1butnotstr2
This commit is contained in:
@@ -2621,9 +2621,12 @@ Usage:
|
|||||||
@brief Returns words that are in both string 1 and string 2
|
@brief Returns words that are in both string 1 and string 2
|
||||||
@details Compares two space separated strings and returns the words that are
|
@details Compares two space separated strings and returns the words that are
|
||||||
in both.
|
in both.
|
||||||
|
|
||||||
|
If either string is empty, nothing is returned.
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
|
|
||||||
%put %mf_wordsInStr1andStr2(
|
%put %mf_wordsinstr1andstr2(
|
||||||
Str1=blah sss blaaah brah bram boo
|
Str1=blah sss blaaah brah bram boo
|
||||||
,Str2= blah blaaah brah ssss
|
,Str2= blah blaaah brah ssss
|
||||||
);
|
);
|
||||||
@@ -2641,34 +2644,26 @@ Usage:
|
|||||||
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
%macro mf_wordsInStr1andStr2(
|
%macro mf_wordsinstr1andstr2(
|
||||||
Str1= /* string containing words to extract */
|
Str1= /* string containing words to extract */
|
||||||
,Str2= /* used to compare with the extract string */
|
,Str2= /* used to compare with the extract string */
|
||||||
)/*/STORE SOURCE*/;
|
)/*/STORE SOURCE*/;
|
||||||
|
|
||||||
%local count_base count_extr i i2 extr_word base_word match outvar;
|
%local count_extr i extr_word outvar;
|
||||||
%if %length(&str1)=0 or %length(&str2)=0 %then %do;
|
%if %length(&str1)=0 or %length(&str2)=0 %then %do;
|
||||||
%put base string (str1)= &str1;
|
%put &sysmacroname: empty input string, nothing to compare;
|
||||||
%put compare string (str2) = &str2;
|
|
||||||
%return;
|
%return;
|
||||||
%end;
|
%end;
|
||||||
%let count_base=%sysfunc(countw(&Str2));
|
|
||||||
%let count_extr=%sysfunc(countw(&Str1));
|
%let count_extr=%sysfunc(countw(&Str1));
|
||||||
|
|
||||||
%do i=1 %to &count_extr;
|
%do i=1 %to &count_extr;
|
||||||
%let extr_word=%scan(&Str1,&i,%str( ));
|
%let extr_word=%scan(&Str1,&i,%str( ));
|
||||||
%let match=0;
|
%if %sysfunc(indexw(%superq(str2),%superq(extr_word)))>0 %then
|
||||||
%do i2=1 %to &count_base;
|
%let outvar=&outvar &extr_word;
|
||||||
%let base_word=%scan(&Str2,&i2,%str( ));
|
|
||||||
%if &extr_word=&base_word %then %let match=1;
|
|
||||||
%end;
|
|
||||||
%if &match=1 %then %let outvar=&outvar &extr_word;
|
|
||||||
%end;
|
%end;
|
||||||
|
/* send out the result without any surrounding whitespace */
|
||||||
&outvar
|
%do;&outvar%end;
|
||||||
|
%mend mf_wordsinstr1andstr2;
|
||||||
%mend mf_wordsInStr1andStr2;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@file
|
@file
|
||||||
@brief Returns words that are in string 1 but not in string 2
|
@brief Returns words that are in string 1 but not in string 2
|
||||||
@@ -2677,9 +2672,12 @@ Usage:
|
|||||||
|
|
||||||
Note - case sensitive!
|
Note - case sensitive!
|
||||||
|
|
||||||
|
If str1 is empty, nothing is returned. If str2 is empty, all the words in
|
||||||
|
str1 are returned.
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
|
|
||||||
%let x= %mf_wordsInStr1ButNotStr2(
|
%let x= %mf_wordsinstr1butnotstr2(
|
||||||
Str1=blah sss blaaah brah bram boo
|
Str1=blah sss blaaah brah bram boo
|
||||||
,Str2= blah blaaah brah ssss
|
,Str2= blah blaaah brah ssss
|
||||||
);
|
);
|
||||||
@@ -2695,34 +2693,26 @@ Usage:
|
|||||||
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
%macro mf_wordsInStr1ButNotStr2(
|
%macro mf_wordsinstr1butnotstr2(
|
||||||
Str1= /* string containing words to extract */
|
Str1= /* string containing words to extract */
|
||||||
,Str2= /* used to compare with the extract string */
|
,Str2= /* used to compare with the extract string */
|
||||||
)/*/STORE SOURCE*/;
|
)/*/STORE SOURCE*/;
|
||||||
|
|
||||||
%local count_base count_extr i i2 extr_word base_word match outvar;
|
%local count_extr i extr_word outvar;
|
||||||
%if %length(&str1)=0 or %length(&str2)=0 %then %do;
|
%if %length(&str1)=0 %then %do;
|
||||||
%put base string (str1)= &str1;
|
%put &sysmacroname: str1 is empty, nothing to compare;
|
||||||
%put compare string (str2) = &str2;
|
|
||||||
%return;
|
%return;
|
||||||
%end;
|
%end;
|
||||||
%let count_base=%sysfunc(countw(&Str2));
|
|
||||||
%let count_extr=%sysfunc(countw(&Str1));
|
%let count_extr=%sysfunc(countw(&Str1));
|
||||||
|
|
||||||
%do i=1 %to &count_extr;
|
%do i=1 %to &count_extr;
|
||||||
%let extr_word=%scan(&Str1,&i,%str( ));
|
%let extr_word=%scan(&Str1,&i,%str( ));
|
||||||
%let match=0;
|
%if %sysfunc(indexw(%superq(str2),%superq(extr_word)))=0 %then
|
||||||
%do i2=1 %to &count_base;
|
%let outvar=&outvar &extr_word;
|
||||||
%let base_word=%scan(&Str2,&i2,%str( ));
|
|
||||||
%if &extr_word=&base_word %then %let match=1;
|
|
||||||
%end;
|
|
||||||
%if &match=0 %then %let outvar=&outvar &extr_word;
|
|
||||||
%end;
|
%end;
|
||||||
|
/* send out the result without any surrounding whitespace */
|
||||||
&outvar
|
%do;&outvar%end;
|
||||||
|
%mend mf_wordsinstr1butnotstr2;
|
||||||
%mend mf_wordsInStr1ButNotStr2;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@file
|
@file
|
||||||
@brief Creates a text file using pure macro
|
@brief Creates a text file using pure macro
|
||||||
|
|||||||
@@ -3,9 +3,12 @@
|
|||||||
@brief Returns words that are in both string 1 and string 2
|
@brief Returns words that are in both string 1 and string 2
|
||||||
@details Compares two space separated strings and returns the words that are
|
@details Compares two space separated strings and returns the words that are
|
||||||
in both.
|
in both.
|
||||||
|
|
||||||
|
If either string is empty, nothing is returned.
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
|
|
||||||
%put %mf_wordsInStr1andStr2(
|
%put %mf_wordsinstr1andstr2(
|
||||||
Str1=blah sss blaaah brah bram boo
|
Str1=blah sss blaaah brah bram boo
|
||||||
,Str2= blah blaaah brah ssss
|
,Str2= blah blaaah brah ssss
|
||||||
);
|
);
|
||||||
@@ -23,31 +26,23 @@
|
|||||||
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
%macro mf_wordsInStr1andStr2(
|
%macro mf_wordsinstr1andstr2(
|
||||||
Str1= /* string containing words to extract */
|
Str1= /* string containing words to extract */
|
||||||
,Str2= /* used to compare with the extract string */
|
,Str2= /* used to compare with the extract string */
|
||||||
)/*/STORE SOURCE*/;
|
)/*/STORE SOURCE*/;
|
||||||
|
|
||||||
%local count_base count_extr i i2 extr_word base_word match outvar;
|
%local count_extr i extr_word outvar;
|
||||||
%if %length(&str1)=0 or %length(&str2)=0 %then %do;
|
%if %length(&str1)=0 or %length(&str2)=0 %then %do;
|
||||||
%put base string (str1)= &str1;
|
%put &sysmacroname: empty input string, nothing to compare;
|
||||||
%put compare string (str2) = &str2;
|
|
||||||
%return;
|
%return;
|
||||||
%end;
|
%end;
|
||||||
%let count_base=%sysfunc(countw(&Str2));
|
|
||||||
%let count_extr=%sysfunc(countw(&Str1));
|
%let count_extr=%sysfunc(countw(&Str1));
|
||||||
|
|
||||||
%do i=1 %to &count_extr;
|
%do i=1 %to &count_extr;
|
||||||
%let extr_word=%scan(&Str1,&i,%str( ));
|
%let extr_word=%scan(&Str1,&i,%str( ));
|
||||||
%let match=0;
|
%if %sysfunc(indexw(%superq(str2),%superq(extr_word)))>0 %then
|
||||||
%do i2=1 %to &count_base;
|
%let outvar=&outvar &extr_word;
|
||||||
%let base_word=%scan(&Str2,&i2,%str( ));
|
|
||||||
%if &extr_word=&base_word %then %let match=1;
|
|
||||||
%end;
|
|
||||||
%if &match=1 %then %let outvar=&outvar &extr_word;
|
|
||||||
%end;
|
%end;
|
||||||
|
/* send out the result without any surrounding whitespace */
|
||||||
&outvar
|
%do;&outvar%end;
|
||||||
|
%mend mf_wordsinstr1andstr2;
|
||||||
%mend mf_wordsInStr1andStr2;
|
|
||||||
|
|
||||||
|
|||||||
@@ -6,9 +6,12 @@
|
|||||||
|
|
||||||
Note - case sensitive!
|
Note - case sensitive!
|
||||||
|
|
||||||
|
If str1 is empty, nothing is returned. If str2 is empty, all the words in
|
||||||
|
str1 are returned.
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
|
|
||||||
%let x= %mf_wordsInStr1ButNotStr2(
|
%let x= %mf_wordsinstr1butnotstr2(
|
||||||
Str1=blah sss blaaah brah bram boo
|
Str1=blah sss blaaah brah bram boo
|
||||||
,Str2= blah blaaah brah ssss
|
,Str2= blah blaaah brah ssss
|
||||||
);
|
);
|
||||||
@@ -24,31 +27,23 @@
|
|||||||
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
%macro mf_wordsInStr1ButNotStr2(
|
%macro mf_wordsinstr1butnotstr2(
|
||||||
Str1= /* string containing words to extract */
|
Str1= /* string containing words to extract */
|
||||||
,Str2= /* used to compare with the extract string */
|
,Str2= /* used to compare with the extract string */
|
||||||
)/*/STORE SOURCE*/;
|
)/*/STORE SOURCE*/;
|
||||||
|
|
||||||
%local count_base count_extr i i2 extr_word base_word match outvar;
|
%local count_extr i extr_word outvar;
|
||||||
%if %length(&str1)=0 or %length(&str2)=0 %then %do;
|
%if %length(&str1)=0 %then %do;
|
||||||
%put base string (str1)= &str1;
|
%put &sysmacroname: str1 is empty, nothing to compare;
|
||||||
%put compare string (str2) = &str2;
|
|
||||||
%return;
|
%return;
|
||||||
%end;
|
%end;
|
||||||
%let count_base=%sysfunc(countw(&Str2));
|
|
||||||
%let count_extr=%sysfunc(countw(&Str1));
|
%let count_extr=%sysfunc(countw(&Str1));
|
||||||
|
|
||||||
%do i=1 %to &count_extr;
|
%do i=1 %to &count_extr;
|
||||||
%let extr_word=%scan(&Str1,&i,%str( ));
|
%let extr_word=%scan(&Str1,&i,%str( ));
|
||||||
%let match=0;
|
%if %sysfunc(indexw(%superq(str2),%superq(extr_word)))=0 %then
|
||||||
%do i2=1 %to &count_base;
|
%let outvar=&outvar &extr_word;
|
||||||
%let base_word=%scan(&Str2,&i2,%str( ));
|
|
||||||
%if &extr_word=&base_word %then %let match=1;
|
|
||||||
%end;
|
|
||||||
%if &match=0 %then %let outvar=&outvar &extr_word;
|
|
||||||
%end;
|
%end;
|
||||||
|
/* send out the result without any surrounding whitespace */
|
||||||
&outvar
|
%do;&outvar%end;
|
||||||
|
%mend mf_wordsinstr1butnotstr2;
|
||||||
%mend mf_wordsInStr1ButNotStr2;
|
|
||||||
|
|
||||||
|
|||||||
@@ -5,12 +5,17 @@
|
|||||||
<h4> SAS Macros </h4>
|
<h4> SAS Macros </h4>
|
||||||
@li mf_wordsinstr1andstr2.sas
|
@li mf_wordsinstr1andstr2.sas
|
||||||
@li mp_assert.sas
|
@li mp_assert.sas
|
||||||
|
@li mp_assertscope.sas
|
||||||
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
|
/* basic test, with scope check */
|
||||||
|
%mp_assertscope(SNAPSHOT)
|
||||||
%let x=%mf_wordsinstr1andstr2(str1=xx DOLLAR x $CHAR xxx W MONNAME
|
%let x=%mf_wordsinstr1andstr2(str1=xx DOLLAR x $CHAR xxx W MONNAME
|
||||||
,str2=DOLLAR $CHAR W MONNAME xxxxxx
|
,str2=DOLLAR $CHAR W MONNAME xxxxxx
|
||||||
);
|
);
|
||||||
|
%mp_assertscope(COMPARE,ignorelist=x)
|
||||||
|
|
||||||
%mp_assert(
|
%mp_assert(
|
||||||
iftrue=(
|
iftrue=(
|
||||||
"&x"="DOLLAR $CHAR W MONNAME"
|
"&x"="DOLLAR $CHAR W MONNAME"
|
||||||
@@ -18,3 +23,92 @@
|
|||||||
desc=Checking basic string,
|
desc=Checking basic string,
|
||||||
outds=work.test_results
|
outds=work.test_results
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/* word boundary - var should not match var1 or var10 */
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(
|
||||||
|
"%mf_wordsinstr1andstr2(str1=var1 var10,str2=var var1)"="var1"
|
||||||
|
),
|
||||||
|
desc=Checking word boundaries,
|
||||||
|
outds=work.test_results
|
||||||
|
)
|
||||||
|
|
||||||
|
/* case sensitivity - dollar does not match DOLLAR */
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(
|
||||||
|
"%mf_wordsinstr1andstr2(str1=DOLLAR dollar,str2=DOLLAR)"="DOLLAR"
|
||||||
|
),
|
||||||
|
desc=Checking case sensitivity,
|
||||||
|
outds=work.test_results
|
||||||
|
)
|
||||||
|
|
||||||
|
/* duplicate words in str1 are preserved */
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(
|
||||||
|
"%mf_wordsinstr1andstr2(str1=a a b,str2=a)"="a a"
|
||||||
|
),
|
||||||
|
desc=Checking duplicate words,
|
||||||
|
outds=work.test_results
|
||||||
|
)
|
||||||
|
|
||||||
|
/* when no words match, nothing is returned */
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(
|
||||||
|
"%mf_wordsinstr1andstr2(str1=a b,str2=c d)"=""
|
||||||
|
),
|
||||||
|
desc=Checking empty result,
|
||||||
|
outds=work.test_results
|
||||||
|
)
|
||||||
|
|
||||||
|
/* when str1 is empty, nothing is returned */
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(
|
||||||
|
"%mf_wordsinstr1andstr2(str1=,str2=a b)"=""
|
||||||
|
),
|
||||||
|
desc=Checking empty str1,
|
||||||
|
outds=work.test_results
|
||||||
|
)
|
||||||
|
|
||||||
|
/* when str2 is empty, nothing is returned */
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(
|
||||||
|
"%mf_wordsinstr1andstr2(str1=a b,str2=)"=""
|
||||||
|
),
|
||||||
|
desc=Checking empty str2,
|
||||||
|
outds=work.test_results
|
||||||
|
)
|
||||||
|
|
||||||
|
/* build strings containing 1000 variables */
|
||||||
|
/* str2 is kept to 100 words to avoid excessive macro iterations */
|
||||||
|
data _null_;
|
||||||
|
length str1 str2 $32767;
|
||||||
|
do i=1 to 1000;
|
||||||
|
word=cats('var',i);
|
||||||
|
str1=catx(' ',str1,word);
|
||||||
|
if mod(i,10)=0 then str2=catx(' ',str2,word);
|
||||||
|
end;
|
||||||
|
call symputx('str1',str1);
|
||||||
|
call symputx('str2',str2);
|
||||||
|
run;
|
||||||
|
|
||||||
|
%mp_assertscope(SNAPSHOT)
|
||||||
|
%let result=%mf_wordsinstr1andstr2(str1=&str1,str2=&str2);
|
||||||
|
%mp_assertscope(COMPARE,ignorelist=result)
|
||||||
|
|
||||||
|
%let count=%sysfunc(countw(&result));
|
||||||
|
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(
|
||||||
|
"&count"="100"
|
||||||
|
),
|
||||||
|
desc=Checking 1000 variable string returns 100 words,
|
||||||
|
outds=work.test_results
|
||||||
|
)
|
||||||
|
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(
|
||||||
|
"&result"="&str2"
|
||||||
|
),
|
||||||
|
desc=Checking 1000 variable string content,
|
||||||
|
outds=work.test_results
|
||||||
|
)
|
||||||
|
|||||||
@@ -5,12 +5,17 @@
|
|||||||
<h4> SAS Macros </h4>
|
<h4> SAS Macros </h4>
|
||||||
@li mf_wordsinstr1butnotstr2.sas
|
@li mf_wordsinstr1butnotstr2.sas
|
||||||
@li mp_assert.sas
|
@li mp_assert.sas
|
||||||
|
@li mp_assertscope.sas
|
||||||
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
|
/* basic test, with scope check */
|
||||||
|
%mp_assertscope(SNAPSHOT)
|
||||||
%let x=%mf_wordsinstr1butnotstr2(str1=xx DOLLAR x $CHAR xxx W MONNAME
|
%let x=%mf_wordsinstr1butnotstr2(str1=xx DOLLAR x $CHAR xxx W MONNAME
|
||||||
,str2=ff xx x xxx xxxxxx
|
,str2=ff xx x xxx xxxxxx
|
||||||
);
|
);
|
||||||
|
%mp_assertscope(COMPARE,ignorelist=x)
|
||||||
|
|
||||||
%mp_assert(
|
%mp_assert(
|
||||||
iftrue=(
|
iftrue=(
|
||||||
"&x"="DOLLAR $CHAR W MONNAME"
|
"&x"="DOLLAR $CHAR W MONNAME"
|
||||||
@@ -18,3 +23,95 @@
|
|||||||
desc=Checking basic string,
|
desc=Checking basic string,
|
||||||
outds=work.test_results
|
outds=work.test_results
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/* word boundary - var1 should not match var10 or var100 */
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(
|
||||||
|
"%mf_wordsinstr1butnotstr2(str1=var1 var10 var100,str2=var1)"
|
||||||
|
="var10 var100"
|
||||||
|
),
|
||||||
|
desc=Checking word boundaries,
|
||||||
|
outds=work.test_results
|
||||||
|
)
|
||||||
|
|
||||||
|
/* case sensitivity - dollar does not match DOLLAR */
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(
|
||||||
|
"%mf_wordsinstr1butnotstr2(str1=DOLLAR dollar,str2=DOLLAR)"="dollar"
|
||||||
|
),
|
||||||
|
desc=Checking case sensitivity,
|
||||||
|
outds=work.test_results
|
||||||
|
)
|
||||||
|
|
||||||
|
/* duplicate words in str1 are preserved */
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(
|
||||||
|
"%mf_wordsinstr1butnotstr2(str1=a a b a,str2=b)"="a a a"
|
||||||
|
),
|
||||||
|
desc=Checking duplicate words,
|
||||||
|
outds=work.test_results
|
||||||
|
)
|
||||||
|
|
||||||
|
/* when all words match, nothing is returned */
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(
|
||||||
|
"%mf_wordsinstr1butnotstr2(str1=a b,str2=b a)"=""
|
||||||
|
),
|
||||||
|
desc=Checking empty result,
|
||||||
|
outds=work.test_results
|
||||||
|
)
|
||||||
|
|
||||||
|
/* when str1 is empty, nothing is returned */
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(
|
||||||
|
"%mf_wordsinstr1butnotstr2(str1=,str2=a b)"=""
|
||||||
|
),
|
||||||
|
desc=Checking empty str1,
|
||||||
|
outds=work.test_results
|
||||||
|
)
|
||||||
|
|
||||||
|
/* when str2 is empty, all of str1 is returned */
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(
|
||||||
|
"%mf_wordsinstr1butnotstr2(str1=a b c,str2=)"="a b c"
|
||||||
|
),
|
||||||
|
desc=Checking empty str2 returns all words,
|
||||||
|
outds=work.test_results
|
||||||
|
)
|
||||||
|
|
||||||
|
/* build strings containing 1000 variables */
|
||||||
|
/* str2 is kept to 100 words to avoid excessive macro iterations */
|
||||||
|
data _null_;
|
||||||
|
length str1 str2 expected $32767;
|
||||||
|
do i=1 to 1000;
|
||||||
|
word=cats('var',i);
|
||||||
|
str1=catx(' ',str1,word);
|
||||||
|
if mod(i,10)=0 then str2=catx(' ',str2,word);
|
||||||
|
else expected=catx(' ',expected,word);
|
||||||
|
end;
|
||||||
|
call symputx('str1',str1);
|
||||||
|
call symputx('str2',str2);
|
||||||
|
call symputx('expected',expected);
|
||||||
|
run;
|
||||||
|
|
||||||
|
%mp_assertscope(SNAPSHOT)
|
||||||
|
%let result=%mf_wordsinstr1butnotstr2(str1=&str1,str2=&str2);
|
||||||
|
%mp_assertscope(COMPARE,ignorelist=result)
|
||||||
|
|
||||||
|
%let count=%sysfunc(countw(&result));
|
||||||
|
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(
|
||||||
|
"&count"="900"
|
||||||
|
),
|
||||||
|
desc=Checking 1000 variable string returns 900 words,
|
||||||
|
outds=work.test_results
|
||||||
|
)
|
||||||
|
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(
|
||||||
|
"&result"="&expected"
|
||||||
|
),
|
||||||
|
desc=Checking 1000 variable string content,
|
||||||
|
outds=work.test_results
|
||||||
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user