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

If I have an array testarray(2,4,6,8); I can use dim(testarray,i) to get the dimension of each index but how do I get the total number of dimensions? (in this case I want to return a 4).

 

  I see ndims exits for other sas products but not for base sas.  currently I loop  i until I get a missing value from  dim(testarray,i) but that feels rather inelegant.

 

Thanks

 

1 ACCEPTED SOLUTION

Accepted Solutions
Tom
Super User Tom
Super User

Macros are not really called "in a data step". The macro processor runs first and then the data step compiler interprets the resulting code. 

As I said if the macro only generates statements that can be embedded in a data step then just add a parameter to the macro so that the person (or macro) that is generating the data step can pass in the number.

data want;
  array myarray [3,4,5] _temporary_;
  %mymacro(name=myarray,ndim=3);
run;

You could make it easier on the coder by just passing in the same information they need to code to make the array and have the macro do the counting for them.

 

data want;
  array myarray [3,4,5] _temporary_;
  %mymacro(array_definition=myarray[3,4,5] );
run;

View solution in original post

9 REPLIES 9
Tom
Super User Tom
Super User

Is this just a theoretical question? The person writing the data step needs to have defined the array, so they already know how many dimensions it has.  The DIM() function is useful because you can define an array without knowing the number of elements.  For example when using a variable list.

array _num _numeric_;

But you cannot define an array with more than one dimensions without actually specifying the dimensions.

weg
Obsidian | Level 7 weg
Obsidian | Level 7

No, its not theoretical.  I have to write a macro that automates many different scripts that each use a lot of arrays of different sizes, usually between 2 and 10 different dimensions.  So I need to be able to get the number of dimensions for my macro.

 

This is what I currently have hacked together and it works, but it is ugly and inefficient:

 

retain ndims 0;
flag = 0;
do while (flag = 0);
	b = ndims + 1;
	if missing(dim(Harray,b)) then 
		flag = 1;
	else
			ndims = b;
		end;
	put ndims=;		

 

 

 

Tom
Super User Tom
Super User
Same logic applies for a macro. If the macro created the data step then it knows how many dimensions it used when it defined the array. If you are writing a macro that generates part of a data step then one of the inputs needs to be the number of dimensions of the array.
weg
Obsidian | Level 7 weg
Obsidian | Level 7
No the macro is called within the data step, the arrays have already been created and populated and they are passed to the macro (among other things). I could make the size an argument to pass to the macro but if my macro can figure out the size then I should just do that.

But I take it there is no easy function to call to do this?
Tom
Super User Tom
Super User

Macros are not really called "in a data step". The macro processor runs first and then the data step compiler interprets the resulting code. 

As I said if the macro only generates statements that can be embedded in a data step then just add a parameter to the macro so that the person (or macro) that is generating the data step can pass in the number.

data want;
  array myarray [3,4,5] _temporary_;
  %mymacro(name=myarray,ndim=3);
run;

You could make it easier on the coder by just passing in the same information they need to code to make the array and have the macro do the counting for them.

 

data want;
  array myarray [3,4,5] _temporary_;
  %mymacro(array_definition=myarray[3,4,5] );
run;
Tom
Super User Tom
Super User

If you want a cleaner version of that hack:

  if _n_=1 then do while(not missing(dim(harray,ndims+1))); ndims+1; end;

But it will still generate the nasty notes in the log.

NOTE: Invalid argument to function DIM at line 243 column 39.
ndims=2
ndims=2 _ERROR_=1 _N_=1
NOTE: Mathematical operations could not be performed at the following places. The results of the
      operations have been set to missing values.
      Each place is given by: (Number of times) at (Line):(Column).
      1 at 243:39
mkeintz
PROC Star

I don't know if it's more efficient, but it's definitely less ugly:

 

   do ndim=0 by 1 while (dim(harray,ndim+1)^=.);
   end;
   put ndim=;
--------------------------
The hash OUTPUT method will overwrite a SAS data set, but not append. That can be costly. Consider voting for Add a HASH object method which would append a hash object to an existing SAS data set

Would enabling PROC SORT to simultaneously output multiple datasets be useful? Then vote for
Allow PROC SORT to output multiple datasets

--------------------------
FreelanceReinh
Jade | Level 19

To avoid "the nasty notes in the log" with your algorithm, you could use something like this:

_t=n(of harray[*])+nmiss(of harray[*]);
do ndim=1 by 1 until(_t=1);
  _t=_t/dim(harray,ndim);
end;

Obviously, the initialization of _t assumes a numeric array. For a character array (in the absence of a character analog of the N function) you could use something like

_t=countw(catx('~',of harray[*]),'~')+cmiss(of harray[*]);

or, if the defined length of the character variables is known (e.g., stored in a variable len)

_t=lengthc(cat(of harray[*]))/len;

 

weg
Obsidian | Level 7 weg
Obsidian | Level 7

OK that is super clever. Best solution to my problem thank you.

sas-innovate-2024.png

Available on demand!

Missed SAS Innovate Las Vegas? Watch all the action for free! View the keynotes, general sessions and 22 breakouts on demand.

 

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.

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
  • 9 replies
  • 768 views
  • 3 likes
  • 4 in conversation