|
Subject: Using Macro Variables as Arrays
Summary: Array without macro code, with macro code, the implied
lookup problem are answered.
Respondent: Ian Whitlock <whitloi1@westat.com>
Chris Stricland <STRICKLA%30747.decnet@JS-JTF.AF.MIL> explains
>Basically, I'm wanted to loop through and looke at vehnum1, vehnum2,
>vehnum3, and vehnum4.
after giving code to create the macro array and a nonworking DATA step
to use it in a data array.
First I generated test data.
data target ;
input vehid @@ ;
cards ;
11 18 23 57
run;
data possible ;
input gpsveh ;
cards ;
12
10
18
23
run ;
Here is code to make the macro array and put it into a data array
without macro code. This basically answers Chris's question in a style
that works and is close to his original code.
data _null_ ;
set target end = eof ;
call symput("vehnum"||put(_n_,1.),vehid);
if eof then do;
call symput ("vehtot",put(_n_,1.));
end;
run ;
data info ;
array veh (&vehtot) ;
retain veh1 - veh&vehtot ;
array wanted (&vehtot) _temporary_ ;
if _n_ = 1 then
do ;
do i = 1 to &vehtot ;
wanted ( i ) = symget ( 'vehnum' || put ( i, 1. ) ) ;
end ;
end ;
set possible ;
do i = 1 to 4 until ( out = 1 ) ;
if gpsveh = wanted ( i ) then
do ;
out = 1 ;
output ;
end ;
end ;
run ;
Filling a data array gets a little easier when macro code is used.
%macro demo ;
%local i vehtot ;
data _null_ ;
set target end = eof ;
call symput("vehnum"||put(_n_,1.),vehid);
if eof then do;
call symput ("vehtot",put(_n_,1.));
end;
run ;
data info ;
array wanted (&vehtot) _temporary_
( %do i = 1 %to &vehtot ; &&vehnum&i %end ;
) ;
set possible ;
do i = 1 to &vehtot until ( found ) ;
if wanted ( i ) then
do ;
found = 1 ;
output ;
end ;
end ;
run ;
%mend demo ;
options mprint ;
%demo
Finally we get to the implied problem - how do you subset a file based
on a lookup list of values? Note that this code is simpler, uses no
macro and executes faster than either interpretation of the explicit
question.
data fmtdata ;
retain fmtname 'wanted' label 'w' ;
set target ( rename = ( vehid = start ) ) ;
run ;
proc format cntlin = fmtdata ;
run ;
data info ;
set possible ;
where put ( gpsveh , wanted1. ) = 'w' ;
run ;
Of course sometimes the simple sort and merge would be best.
Ian Whitlock
|