2 min read

List Processing With SAS (1): List Creating I

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:

https://github.com/Jiangtang/SAS_ListProcessing/

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