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

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

 

1 ACCEPTED SOLUTION

Accepted Solutions
ballardw
Super User

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

 

View solution in original post

15 REPLIES 15
andreas_lds
Jade | Level 19

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.

meichan1128
Calcite | Level 5
sorry it doesnt,,,,
andreas_lds
Jade | Level 19

Please explain how you plan to use the array you think you need.

Shmuel
Garnet | Level 18

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);
meichan1128
Calcite | Level 5
i have posted my solution. thank you.
ballardw
Super User

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.

 

meichan1128
Calcite | Level 5
i have posted my solution. thank you.
PeterClemmensen
Tourmaline | Level 20

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;
meichan1128
Calcite | Level 5

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

 

Shmuel
Garnet | Level 18

@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;

 

 

 

Shmuel
Garnet | Level 18

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

 

 

ballardw
Super User

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

 

meichan1128
Calcite | Level 5

thank you so much ! this is what exactly I wanted !

Tom
Super User Tom
Super User

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

SAS Innovate 2025: Register Now

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!

How to Concatenate Values

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.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 15 replies
  • 2068 views
  • 3 likes
  • 7 in conversation