- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
In a code snippet not shown here I use the coalesce(c) functions in an array context.
But I want the coalesce function to start from the last element of the array.
I've found a workaround for my code but I wonder if I can invert the order of an array.
For sure I could use 'do dim(array) to 1...' but this doesn't work for 'of array[*]' usage.
So in my basic example I want to array _var to have weight as the first element without changing the order for which it was defined.
data class;
set sashelp.class;
run;
data class2;
set class;
array _var (3) Age Height Weight;
array _retain (3) _Age _Height _Weight;
array _mult (3) (1 2 3);
do i=1 to dim (_var);
_retain(i)=_var(i)*_mult(i);
end;
run;
array temp1 (4) type_files1 type_files2 type_files3 type_files4;
lastnonmiss1=whichc(coalescec(of temp1[*]), of temp1[*]);
Accepted Solutions
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
Reverse an array like this, then you can do anything you want with it.
data a;
array temp temp1-temp4;
array reverse(4) _temporary_;
temp1=1;
temp2=2;
temp3=.;
temp4=.;
do i=1 to dim(temp);
reverse(i)=temp(dim(temp)-i+1);
end;
calc = coalesce(of reverse{*});
drop i;
run;
Paige Miller
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
loop from last to first and compare manually:
do i=dim(temp1) to 1;
if vvalue(temp1[i]) eq coalescec(of temp1[*]) then lastnonmiss1=i;
end;
- Cheers -
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
@Oligolas wrote:
Hi,
loop from last to first and compare manually:
do i=dim(temp1) to 1; if vvalue(temp1[i]) eq coalescec(of temp1[*]) then lastnonmiss1=i; end;
UNTESTED but shouldn't that say
do i=dim(temp1) to 1 by -1;
?
Paige Miller
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
of course, it's by -1
My mistake
- Cheers -
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
Thanks, nice trick but it doesn't solve my challenge.
The array elements were constructed from left to right if available meaning that if my array dimension is 4 then the elements could be
temp1(1)=csv
temp1(2)=xlsx
temp1(3)=''
temp1(4)=''
Your code still resolves to 1 (or 4 in your inverse order) as the condition becomes true for the coalescec result that in my understanding is still the first array element.
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
Reverse an array like this, then you can do anything you want with it.
data a;
array temp temp1-temp4;
array reverse(4) _temporary_;
temp1=1;
temp2=2;
temp3=.;
temp4=.;
do i=1 to dim(temp);
reverse(i)=temp(dim(temp)-i+1);
end;
calc = coalesce(of reverse{*});
drop i;
run;
Paige Miller
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
With FCMP you can write your own COALESCECR function, however due to limitations of FCMP the implementation would accept only a character array (not an OF var(*) argument which expands to a variable number of individual arguments), OR a fixed number of arguments (not useful)
options cmplib='';
proc fcmp outlib=sasuser.sandbox.udf;
function coalescecR(s(*) $) $ 200;
do index = dim(s) to 1 by -1;
if not missing(s[index]) then return (s[index]);
end;
return ('');
endsub;
quit;
options cmplib=sasuser.sandbox;
data want; set have; array s a b c d e f g; lastc = coalescecR(s); /* <------------------- */ put lastc=; run;
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
For numbered range lists (as in your second example) you can reverse the order without an array:
data have; array tf[4] $ ('csv' 'xlsx' ' ' ' '); run; data want; set have; lastnonmiss=whichc(coalescec(of tf4-tf1), of tf1-tf4); run;
These reversed ranges can also be used in an array definition:
data want;
set sashelp.pricedata;
array revprice[*] price17-price1;
/* ... */
run;
(so that revprice[1] equals price17, revprice[2] equals price16, etc.).
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
data class; set sashelp.class; run; proc sql noprint; select name into :vnames separated by ' ' from dictionary.columns where libname='WORK' and upcase(name) in ('AGE' 'WEIGHT' 'HEIGHT') order by varnum desc; quit; %put &=vnames. ;
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
And refer to it in your code:
data class2;
set class;
array _var{*} &vnames. ;
......................
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
Why not just list the elements in the opposite order?
The code you posted that is using the array to perform calculations does not depend on the order that the variables are listed in the array definition.
And if you have a simple list of variables with a numeric suffix then you can make a variable list from last to first as easily as from first to last.
Also there is no need to define an array to use the coalescec() function.
lastnonmiss1=coalescec(of type_files4-type_files1);