Desktop productivity for business analysts and programmers

how do we get the position of an elements in a macro variable (macro variable = list of values)

Accepted Solution Solved
Reply
Frequent Contributor
Posts: 111
Accepted Solution

how do we get the position of an elements in a macro variable (macro variable = list of values)

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

 


Accepted Solutions
Solution
‎10-17-2017 07:48 AM
Super User
Posts: 9,604

Re: how do we get the position of an elements in a macro variable (macro variable = list of values)

[ Edited ]

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;
---------------------------------------------------------------------------------------------
Maxims of Maximally Efficient SAS Programmers
How to convert datasets to data steps
How to post code

View solution in original post


All Replies
Solution
‎10-17-2017 07:48 AM
Super User
Posts: 9,604

Re: how do we get the position of an elements in a macro variable (macro variable = list of values)

[ Edited ]

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;
---------------------------------------------------------------------------------------------
Maxims of Maximally Efficient SAS Programmers
How to convert datasets to data steps
How to post code
Frequent Contributor
Posts: 111

Re: how do we get the position of an elements in a macro variable (macro variable = list of values)

Posted in reply to KurtBremser

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

 

 

 

Super User
Posts: 9,604

Re: how do we get the position of an elements in a macro variable (macro variable = list of values)

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).

---------------------------------------------------------------------------------------------
Maxims of Maximally Efficient SAS Programmers
How to convert datasets to data steps
How to post code
Frequent Contributor
Posts: 111

Re: how do we get the position of an elements in a macro variable (macro variable = list of values)

Posted in reply to KurtBremser
Thanks a lot for your answer Kurt!
Super User
Super User
Posts: 7,860

Re: how do we get the position of an elements in a macro variable (macro variable = list of values)

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

☑ This topic is solved.

Need further help from the community? Please ask a new question.

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