This post was kindly contributed by From a Logical Point of View » SAS - go there to comment and to read the full post. |
Suppose you have 10 datasets, literally ds1, ds2, …ds10 and you need to concatenate them all. You may first get a quick shortcut set ds1-ds10. If such list members were generated dynamically (and may hold a form like ds1a, ds2a,… ds10a) , you will probably come out a macro solution:
%macro doit;
data combine;
set %do i=1 %to &n; ds&i %end; ;
run;
%mend;
%doit
where we conduct the list series in a %do loop. Also, suppose we need to fill out a list of datasets in a FROM clause of a SQL procedure. You can not copy the %do loop above because all elements should be separated by a comma. I once wrote a recursive macro to produce such list:
%macro _list(n,pre=ds);
%if &n=1 %then &pre.1;
%else %_list(%eval(&n-1)),&pre.&n;
%mend _list;%put %_list(10);
The question is, how can we produce such list of values at a universal form? I put all my collected SAS list processing utilities (macro like functions) at Github:
and we can begin with macro %range by Ian Whitlock and Chang Chung:
filename list url "https://raw.github.com/Jiangtang/SAS_ListProcessing/master/_ListProcessing";
%inc list;%put %range(to=10);
%put %range(to=10, opre=%str(ds));
%put %range(to=10, opre=%str(ds),osuf=%str(a));
%put %range(from=2,to=10,step=3,osep=%str(,));
%put %range(from=2,to=10,step=3,osep=%str(,),osuf=%str(ds));
The outputs:
1 2 3 4 5 6 7 8 9 10
ds1 ds2 ds3 ds4 ds5 ds6 ds7 ds8 ds9 ds10
ds1a ds2a ds3a ds4a ds5a ds6a ds7a ds8a ds9a ds10a
2,5,8
2ds,5ds,8ds
%range is a very versatile macro like function which accepts lower and upper bounds, increments, separated symbol, prefix and suffix as parameters to create bunch of lists.
Note:
To create a non-integer list, use %range_non_int:
%put %range_non_int(start = 1 , end = 2 , by = .25 ) ;
and you get
1 1.25 1.5 1.75 2
This post was kindly contributed by From a Logical Point of View » SAS - go there to comment and to read the full post. |