BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
alepage
Barite | Level 11

Hello,

 

I need to get the position of a specific value (element) in a macro variable, where the macro variable represent a list of values.

Here's my code

 

data have; 

input unite1 unite2 unite3 unite4 unite5; 

datalines; 

65110 55020 90010 0 0 

; 

run; 

Data _null_; 

%global list1; 

%let list1=65110 55020; 

run; 

%put &list1; 

data want; 

set have; 

array unite{*} unite:; 

do i=1 to dim(unite); 

if unite(i) in &list1 then 

do; 

list_pos=%sysfunc(countw(%substr(&list1,1,%index(&list1,unite(i))+1))); 

end; 

end; 

 

run;

 

When I replace unite(i) in the list_post definition by a number, it works. Is it possible to use unite(i) and if so, which correction should I bring to my code.

 

Regards,

Alain

 

1 ACCEPTED SOLUTION

Accepted Solutions
Kurt_Bremser
Super User

Usual misunderstanding of what the macro PREprocessor does, and when.

The %syfunc is evaluated while the code for the data step is fetched for compilation, so it does have NO access to data step variables (which start to exist when the data step has been compiled and executes).

Some other remarks in the comments:

data have;
input unite1 unite2 unite3 unite4 unite5;
datalines;
65110 55020 90010 0 0
;
run;

Data _null_; /* this (and the accompanying run) is useless; macro triggers are resolved by the macro preprocessor immediately when encountered in text. No step around them is needed */
%global list1; /* not necessary; this happens outside a macro defintion, so all macro variables will be created in the global table */
%let list1=65110 55020;
run; /* see above */

%put &list1;

data want;
set have;
array unite{*} unite:;
do i=1 to dim(unite);
  if unite(i) in &list1 then
  do;

    list_pos=%sysfunc(countw(%substr(&list1,1,%index(&list1,unite(i))+1))); 
    /* %index(&list1,unite(i)) : the macro preprocessor will try to find the TEXT "unite(i)" in &list1, will not find it, so it returns 0 */
  end;
end;
run;

and for $DEITY's sake, use the "little running man" icon for posting code. Posting code in the main window messes it up. I had to remove all kinds of spurious crap from your code just to get it running.

Did you want do do this?

data want;
set have;
array unite{*} unite:;
do i=1 to dim(unite);
  if unite{i} in (&list1) then do;
    list_pos = countw(substr("&list1",1,index("&list1",strip(put(unite(i),best.)))+1));
  end;
end;
run;

View solution in original post

5 REPLIES 5
Kurt_Bremser
Super User

Usual misunderstanding of what the macro PREprocessor does, and when.

The %syfunc is evaluated while the code for the data step is fetched for compilation, so it does have NO access to data step variables (which start to exist when the data step has been compiled and executes).

Some other remarks in the comments:

data have;
input unite1 unite2 unite3 unite4 unite5;
datalines;
65110 55020 90010 0 0
;
run;

Data _null_; /* this (and the accompanying run) is useless; macro triggers are resolved by the macro preprocessor immediately when encountered in text. No step around them is needed */
%global list1; /* not necessary; this happens outside a macro defintion, so all macro variables will be created in the global table */
%let list1=65110 55020;
run; /* see above */

%put &list1;

data want;
set have;
array unite{*} unite:;
do i=1 to dim(unite);
  if unite(i) in &list1 then
  do;

    list_pos=%sysfunc(countw(%substr(&list1,1,%index(&list1,unite(i))+1))); 
    /* %index(&list1,unite(i)) : the macro preprocessor will try to find the TEXT "unite(i)" in &list1, will not find it, so it returns 0 */
  end;
end;
run;

and for $DEITY's sake, use the "little running man" icon for posting code. Posting code in the main window messes it up. I had to remove all kinds of spurious crap from your code just to get it running.

Did you want do do this?

data want;
set have;
array unite{*} unite:;
do i=1 to dim(unite);
  if unite{i} in (&list1) then do;
    list_pos = countw(substr("&list1",1,index("&list1",strip(put(unite(i),best.)))+1));
  end;
end;
run;
alepage
Barite | Level 11

Yes, Kurt, it is exactly what I want to do.

 

Regarding the %sysfunc use, you have retrieve it from the code.  So, when should I use it?  (do you have something (document pdf) on its use?

 

Finally, where is the little running man you are referring to?

Regards,

Alain

 

 

 

Kurt_Bremser
Super User

You use %sysfunc to get the functionality of a data step function in a macro statement. Although you get access to the function, this still happens completely outside any data step, while macro triggers are resolved.

 

When you post, you have a series of icons right above the main posting window. The sixth looks like {i} and is ideal for logs or raw data, the seventh (little running man) looks like the "submit" button in SAS and is good for code, as it simulates the coloring of the Enhanced Editor.

Both of these posting methods post text as is, without any web-typical formatting (and character translation).

Tom
Super User Tom
Super User

You cannot reference data step variables in macro code. The macro processors work is done before the data step starts to run.

It looks like you want to find the position of a value in the list defined by the values in the macro variable?

The WHICHN() function (or WHICHC for character strings) is useful for that.

You use the macro variable value to generate an temporary array and then use the WHiCHN() function to find the location in that array.

%let list1=65110 55020; 

data have; 
 input unite1-unite5; 
datalines; 
65110 55020 90010 0 0 
; 

data want; 
  set have; 
  array unite(5) ;
  array list_pos (5) ; 
  array list (%sysfunc(countw(&list1))) _temporary_ (&list1)  ;
  do i=1 to dim(unite); 
    list_pos(i)=whichn(unite(i),of list(*));
  end;
  drop i;
run;

image.png

sas-innovate-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

Register now!

SAS Enterprise Guide vs. SAS Studio

What’s the difference between SAS Enterprise Guide and SAS Studio? How are they similar? Just ask SAS’ Danny Modlin.

Find more tutorials on the SAS Users YouTube channel.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 5 replies
  • 2175 views
  • 0 likes
  • 3 in conversation