SyntaxHighlighter

Wednesday, November 20, 2013

The Need for Speed - %SCAN loop

Have you ever had to write a macro to parse words in a string using the %SCAN function and wondered what is the best, most efficient technique? The below code compares the time it takes to do this using three different techniques.

In my test, I repeated the 26 letters of the alphabet 10 times so that a total of 260 scans are performed as a benchmark. Review the below code and then see the bar chart of the average time it took after five attempts of each macro. It is clearly best to use the COUNTW() function once to detemine the number of times to loop.

data _null_ ;
  length string $1028 ;
  do i = 1 to 10 ;
    do j = 65 to 90 ;
      string = catx( " ", string, byte( j ) ) ;
     end ;
  end ;
  call symput( 'macvar', string ) ;
run ;

%let starttime = %sysfunc( datetime() ) ;
%macro good ;
  %local i retval ;
  %let i = 1 ;
  %do %while( %scan( &macvar., &i. ) ne ) ;
    %let i = %eval( &i + 1 ) ;
    %let retval = %scan( &macvar., &i. ) ;
  %end ;
%mend ;
%put %sysevalf( %sysfunc(datetime()) - &starttime. ) ;

%let starttime = %sysfunc( datetime() ) ;
%macro better ;
  %local i retval ;
  %let i = 1 ;
  %let retval = %scan( &macvar., &i. ) ;
  %do %while( &retval. ne ) ;
    %let i = %eval( &i. + 1 ) ;
    %let retval = %scan( &macvar., &i. ) ;
  %end ;
%mend ;
%better
%put %sysevalf( %sysfunc(datetime()) - &starttime. ) ;

%let starttime = %sysfunc( datetime() ) ;
%macro best ;
  %local i retval ;
  %let totalwords = %sysfunc( countw( &macvar ) ) ;
  %do i = 1 %to &totalwords ;
    %let retval = %scan( &macvar., &i. ) ;
  %end ;
%mend ;
%best
%put %sysevalf( %sysfunc(datetime()) - &starttime. ) ;

Click graph for a sharper image.