マクロの%doループはループ値にリスト形式の離散値は指定できないので、工夫しようの話

例えば適当なマクロがあったとして

%macro a(no);
data DS&no;
a=&no;
run;
%mend a;

このマクロaのパラメータを1から7で実行したいと思えば

%macro tloop;
%do i = 1 to 7 ;
%a( &i )
%end;
%mend tloop;

として、

%tloop

とすればできます。

ではパラメータが1 3 5 7のように非連続であればどうしましょう?

%macro _tloop;
%do i = 1 , 3 , 5 , 7 ;
%a( &i )
%end;
%mend _tloop;

%_tloop


とかって書きたいところですが、こいつは漏れなくエラーです。

通常のデータステップのdoステートメントでは

do i = 1 , 3, 5, 7;end; のような非連続値をリスト形式で指定して回せますが
マクロの%do はできません。基本的には別物だと考えた方がいいでしょう。


でも、どうしても、非連続のループがやりたいのって場合はどうするか。
ぱっと思いつく範囲で書いてみました。


まずパターン1として、今回はパラメータを変えながらマクロを実行したいだけなので
ループ用マクロを作らずに通常のデータステップの、do ループで値を遷移させて
call executeしちゃうパターン

data _null_;
do i = 1 , 3 , 5 , 7;
call execute( cats( '%a(' , i ,')' ));
end;
run;


つづいてパターン2 として minoperator オプションを使って
マクロ内でのin演算子を有効にし、ループ変数の最小最大値でループして
inでターゲットの非連続値の値が来た時のみ実行するパターン

%macro loop;
options minoperator;
%do i = 1 %to 7;
%if &i in 1 3 5 7 %then %a(&i);
%end;
options nominoperator;
%mend loop;

%loop



パターン3はインデックス値をマクロ変数で与えて%scanで代入していくパターン

%macro loop2 ;
 %let loopval =1 3 5 7; 
   %let i = 1 ;                 
   %do %until(%scan(&loopval,&i) eq) ;
      %let j = %scan(&loopval,&i);
     %a(&j)
      %let i = %eval(&i+1) ;
   %end ;                       
%mend loop2;                

%loop2

パターン4 はパターン3と発想は同じで、よりシンプルな書き方

%macro loop3;
%let loopval=1 3 5 7;
%do i=1 %to %sysfunc(countw(&loopval));
%let j=%scan(&loopval,&i);
   %a(&j)
%end;
%mend;

%loop3;


パターン2以外は、多分ループ用に与えたい値が文字であっても
そのまま応用できると思います。

また、多分、他にもいろいろ書けるとは思います

0 件のコメント:

コメントを投稿