BookmarkSubscribeRSS Feed
☑ This topic is solved. Need further help from the community? Please sign in and ask a new question.
acordes
Rhodochrosite | Level 12

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[*]);

 

1 ACCEPTED SOLUTION

Accepted Solutions
PaigeMiller
Diamond | Level 26

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

View solution in original post

10 REPLIES 10
Oligolas
Barite | Level 11

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 -

PaigeMiller
Diamond | Level 26

@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
Oligolas
Barite | Level 11

of course, it's by -1

My mistake

________________________

- Cheers -

acordes
Rhodochrosite | Level 12

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.

PaigeMiller
Diamond | Level 26

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
RichardDeVen
Barite | Level 11

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)

Spoiler
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;
FreelanceReinh
Jade | Level 19

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 price17revprice[2] equals price16, etc.).

Ksharp
Super User
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. ;
Ksharp
Super User
You could make a macro to contain the variable name which have the reverse order. As above.
And refer to it in your code:

data class2;
set class;
array _var{*} &vnames. ;
......................
Tom
Super User Tom
Super User

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

 

sas-innovate-wordmark-2025-midnight.png

Register Today!

Join us for SAS Innovate 2025, our biggest and most exciting global event of the year, in Orlando, FL, from May 6-9. Sign up by March 14 for just $795.


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
  • 10 replies
  • 2789 views
  • 9 likes
  • 7 in conversation