Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SAS - Define array of letters

Tags:

sas

Is there a shorthand in SAS for defining a sequence of letters in an array?

Many languages possess a mechanism for doing so easily and I imagine SAS does too, although I'm unable to find a reference for it.

For instance, in R I could do

> x <- letters[1:4]
> x
[1] "a" "b" "c" "d"

In Python, one way is

>>> import string
>>> list(string.ascii_lowercase[:4])
['a', 'b', 'c', 'd']

In SAS, I currently am having to list the letters explicitly,

data _null_;
  array letters (4) $ _temporary_ ('a', 'b', 'c', 'd');
  do i = 1 to hbound(letters);
    put letters(i);
  end;
run;
like image 380
Lorem Ipsum Avatar asked Jul 20 '17 15:07

Lorem Ipsum


People also ask

How do I initialize an array in SAS?

To initialize a static multidimensional array, use the ARRAY or DECLARE statement to list values for the first row of the array, followed by values for the second row, and so on.

What is a char array?

A character array is a sequence of characters, just as a numeric array is a sequence of numbers. A typical use is to store a short piece of text as a row of characters in a character vector.

How do you define a range in an array?

Array range notation is a shorthand notation to facilitate passing of array variables to built-in, internal and external Functions and Procedures. A range of array variables can be indicated by separating the first array index value from the last index value by two decimal points.

What is a SAS array?

A SAS array is a convenient way of temporarily identifying a group of variables for processing within a data step. Once the array has been defined the programmer is now able to perform the same tasks for a series of related variables, the array elements.


3 Answers

You can use the COLLATE() to generate a string of single byte characters. If you don't know the ASCII code for the start of the block of characters you want then use the RANK() function.

So if you only want four characters start from 'a' you could do it this way.

  length str $4 ;
  str = collate(rank('a'));

Or you could also use the optional second parameter to COLLATE() to specify how many characters you want.

  length str $4 ;
  str = collate(rank('a'),rank('a')+vlength(str)-1);

There is no need for an "array", just use a variable.

data _null_;
  length str $4 ;
  str = collate(rank('a'));
  do i=1 to vlength(str);
    ch = char(str,i);
    put i= ch= :$quote. ;
  end;
run;

Result:

i=1 ch="a"
i=2 ch="b"
i=3 ch="c"
i=4 ch="d"
like image 89
Tom Avatar answered Oct 17 '22 10:10

Tom


Not that I'm aware of, but it is trivial to write a macro to do that.

%macro letter_sequence(start=1,end=, lower=1);
  %local i addon;
  %if &lower=1 %then %let addon=96;
  %else %let addon=64;
  %do i = &start+&addon. %to &end.+&addon.;
    "%sysfunc(byte(&i.))"
  %end;
%mend letter_sequence;

data test;
  array x[4] $ (%letter_sequence(end=4));
  put x[2]=;
run;
like image 38
Joe Avatar answered Oct 17 '22 10:10

Joe


Another option is to use the collate function and the call pokelong routine:

/*Upper case*/
data _null_;
  array a[26] $1;
  call pokelong(collate(65,65+25),addrlong(a1),26);
  put _All_;
run;

/*Lower case*/
data _null_;
  array a[26] $1;
  call pokelong(collate(97,97+25),addrlong(a1),26);
  put _All_;
run;

This bypasses all the usual mechanisms for assigning values for individual variables and takes advantage of the default memory layout used by SAS for character arrays, copying the whole alphabet in one go starting at the address for the first element.

N.B. call pokelong might not be available in some locked-down SAS environments, e.g. SAS University Edition. Also, this might not work properly with temporary arrays in SAS 9.1.3 or earlier on some platforms.

I think this is the only way to do this in SAS without either hard-coding your letters or writing some sort of loop.

like image 36
user667489 Avatar answered Oct 17 '22 11:10

user667489