I wonder how to make use of the existing array to create another array. thanks
%macro test(varlist)
data test;
set test;
array var_arr (*) &varlist;
array var_arr2 (*) &varlist_1;
run;
but it did not work...
I want to declare the following with var_arr(*):
array var_arr2 (*) a_1 b_1 c_1;
thank you very much
@meichan1128 wrote:
Thank you guys for answering my question. After doing some researching, I came up with the following, and solved my problem:
%macro test(varlist); %let varlist_1 = %sysfunc(tranwrd(&varlist, %str( ), %str(_1 ))); data _null_; set test; array var_arr (*) &varlist.; array var_arr2 (*) &varlist_1.; run; %mend;
%let varlist = a b c;
%test(varlist);
This "solution" fails when your varlist has exactly one element.
%macro dummy(varlist); %let varlist_1 = %sysfunc(tranwrd(&varlist, %str( ), %str(_1 ))); %put varlist_1 is: &varlist_1.; %mend; %let varlist = a; %dummy(a);
The result of your approach means that Varlist_1 is exactly the same as Varlist with exactly one element.
Also, if you ever have more than one space in the middle of the list it fails the intended purpose by creating multiple _1 for each space
%dummy(a b c); yields varlist_1 is: a_1 _1 b_1 _1 _1 _1 c
And it fails for your basic approach: the LAST element of varlist from %let varlist= a b c ; is not suffixed.
%let varlist = a b c ; %dummy(&varlist.); yields varlist_1 is: a_1 b_1 c
This last case is because there is no space after the last character. You can check how the macro processor handles such by:
%let varlist = a b c ; %put &varlist^;
The macro processor ignores trailing blanks. So the result of the %put above is a b c^
If you go back to my example possibly proposed solution you will see that varlist= a b c ; yields the expected values. That is because of the way the countw and Scan work by default with repeated delimiters
data _null_; x="a b c"; length y $ 200; do i= 1 to countw(x); item=scan(x,i); put item=; word= catx('_',scan(x,i),'1'); put word=; y=catx(' ',y,word); put y=; end; run;
shows the string being built.
A macro solution could look like:
%macro dummy(varlist); %local varlist_1; %let varlist_1=; %do i=1 %to %sysfunc(countw(&varlist.)); %let varlist_1 = &varlist_1. %scan(&varlist.,&i)_1; %end; %put Varlist_1 is: &varlist_1.; %mend; %let varlist = a b c; %dummy(&varlist.);
If you want to just build the VARLIST_1 macro variable and use it elsewhere change the %local to %global to make it available outside of the %dummy macro.
An array is only a shortcut to access existing variables. Arrays can have more than one dimension, which is maybe what you want/need. The array statement is, of course, well documented.
Please explain how you plan to use the array you think you need.
1) What variables should be assigned to each of the two arrays you want ?
2) You are using macro variable &varlist_1 which was not defined.
You probably wanted to add suffix _1 to each member of the list, then you have to
create a macro loop to create the new array as in next tested code:
options mprint;
%macro test(varlist);
data _null_;
set test;
array var_arr1 {*} &varlist;
array var_arr2 {*}
%let n = %sysfunc(countw(&varlist));
%do i=1 %to &n;
%scan(&varlist,&i)_1
%end;
; /* closing the array statement */
run cancel;
%mend;
%test(a b c d);
How do you build varlist1? It may be easiest to build the "new" list in parallel.
If you expect to do this frequently then you need to build a tool that will do so.
Note that you very cleverly did not show us what your existing varlist actually looks like.
Assuming you started with Varlist = a b c then consider:
%let varlist=a b c; data _null_; x="&varlist."; length y $ 200; do i= 1 to countw(x); word= catx('_',scan(x,i),'1'); y=catx(' ',y,word); end; call symputx ('varlist_1',y); run; %put New list is: &varlist_1.;
BTW: Doesn't work is awful vague.
Are there errors in the log?: Post the code and log in a code box opened with the <> to maintain formatting of error messages.
No output? Post any log in a code box.
Unexpected output? Provide input data in the form of data step code pasted into a code box, the actual results and the expected results. Instructions here: https://communities.sas.com/t5/SAS-Communities-Library/How-to-create-a-data-step-version-of-your-dat... will show how to turn an existing SAS data set into data step code that can be pasted into a forum code box using the </> icon or attached as text to show exactly what you have and that we can test code against.
Like the other responders, I am unsure what you actually want to do and what fails.
The subject title however leads my mind to the implicit array, which can be created using other arrays. See a small example below.
data _null_;
array a a1-a5;
array b b1-b5;
array ab a b;
run;
Thank you guys for answering my question. After doing some researching, I came up with the following, and solved my problem:
%macro test(varlist);
%let varlist_1 = %sysfunc(tranwrd(&varlist, %str( ), %str(_1 )));
data _null_;
set test;
array var_arr (*) &varlist.;
array var_arr2 (*) &varlist_1.;
run;
%mend;
%let varlist = a b c;
%test(varlist);
@meichan1128 wrote:
Thank you guys for answering my question. After doing some researching, I came up with the following, and solved my problem:
%macro test(varlist); %let varlist_1 = %sysfunc(tranwrd(&varlist, %str( ), %str(_1 ))); data _null_; set test; array var_arr (*) &varlist.; array var_arr2 (*) &varlist_1.; run; %mend;
%let varlist = a b c;
%test(varlist);
Your code will not generate correct code in case you have more then one space between variables as in: %test(a b c); as it generated the code:
MPRINT(TEST): array var_arr2 (*) a_1 _1 _1 b_1 _1 _1 c;
I have checked with
%let varlist_1 = %sysfunc(tranwrd(%sysfunc(compbl(&varlist)), %str( ), %str(_1 )));
but even then the last variable is still not correct, it generated:
MPRINT(TEST): array var_arr2 (*) a_1 b_1 c;
An alternate solution will be:
%macro test(varlist);
%let varlist_1 = %sysfunc(compbl(&varlist));
%let varlist_2 = %sysfunc(tranwrd(&varlist_1,%str( ),%str(. ))).;
%let varlist_3 = %sysfunc(tranwrd(&varlist_2, %str(.), %str(_1 )));
%put 1=&varlist_1 2=&varlist_2 3=&varlist_3;
%mend;
options mprint;
%test(a b c );
with the required result (copied from the log):
1=a b c 2=a. b. c. 3=a_1 b_1 c_1
@meichan1128 wrote:
Thank you guys for answering my question. After doing some researching, I came up with the following, and solved my problem:
%macro test(varlist); %let varlist_1 = %sysfunc(tranwrd(&varlist, %str( ), %str(_1 ))); data _null_; set test; array var_arr (*) &varlist.; array var_arr2 (*) &varlist_1.; run; %mend;
%let varlist = a b c;
%test(varlist);
This "solution" fails when your varlist has exactly one element.
%macro dummy(varlist); %let varlist_1 = %sysfunc(tranwrd(&varlist, %str( ), %str(_1 ))); %put varlist_1 is: &varlist_1.; %mend; %let varlist = a; %dummy(a);
The result of your approach means that Varlist_1 is exactly the same as Varlist with exactly one element.
Also, if you ever have more than one space in the middle of the list it fails the intended purpose by creating multiple _1 for each space
%dummy(a b c); yields varlist_1 is: a_1 _1 b_1 _1 _1 _1 c
And it fails for your basic approach: the LAST element of varlist from %let varlist= a b c ; is not suffixed.
%let varlist = a b c ; %dummy(&varlist.); yields varlist_1 is: a_1 b_1 c
This last case is because there is no space after the last character. You can check how the macro processor handles such by:
%let varlist = a b c ; %put &varlist^;
The macro processor ignores trailing blanks. So the result of the %put above is a b c^
If you go back to my example possibly proposed solution you will see that varlist= a b c ; yields the expected values. That is because of the way the countw and Scan work by default with repeated delimiters
data _null_; x="a b c"; length y $ 200; do i= 1 to countw(x); item=scan(x,i); put item=; word= catx('_',scan(x,i),'1'); put word=; y=catx(' ',y,word); put y=; end; run;
shows the string being built.
A macro solution could look like:
%macro dummy(varlist); %local varlist_1; %let varlist_1=; %do i=1 %to %sysfunc(countw(&varlist.)); %let varlist_1 = &varlist_1. %scan(&varlist.,&i)_1; %end; %put Varlist_1 is: &varlist_1.; %mend; %let varlist = a b c; %dummy(&varlist.);
If you want to just build the VARLIST_1 macro variable and use it elsewhere change the %local to %global to make it available outside of the %dummy macro.
thank you so much ! this is what exactly I wanted !
You left the suffix off the last item in the list. You are calling the macro with just one variable named VARLIST instead of the three you had in the %LET statement. You can use the COMPBL() function to make sure the original list has only one separator between each variable.
%macro test(varlist);
%local varlist_1;
%let varlist=%sysfunc(compbl(&varlist));
%let varlist_1 = %sysfunc(tranwrd(&varlist, %str( ), %str(_1 )))_1;
data _null_;
set test;
array var_arr &varlist.;
array var_arr2 &varlist_1.;
run;
%mend;
%test(a b c);
Registration is now open for SAS Innovate 2025 , our biggest and most exciting global event of the year! Join us in Orlando, FL, May 6-9.
Sign up by Dec. 31 to get the 2024 rate of just $495.
Register now!
Learn how use the CAT functions in SAS to join values from multiple variables into a single value.
Find more tutorials on the SAS Users YouTube channel.
Ready to level-up your skills? Choose your own adventure.