useR
useR

Reputation: 3082

Dynamic dimension of array SAS

I have a data set ADDRESS as shown below

data address;
    input fulladdress $char80.;
    datalines;
RM 101A TOWER 607,PALZZ     ,28 ABC ST     ,DISTRICT 14
FLAT 2426 24/F   ,KKL HSE   ,HAPPY ESTATE  ,DISTRICT 10
FLAT 08 18/F     ,BBC HOUSE ,CDEFG COURT   ,DISTRICT 9  , testingAdd5
;
run;

You may observe that for each observation, address component is seperated by the delimiter "," therefore the dimension of array is dynamic(4 for first two observation and 5 for last observation) .

When i tried at the moment

data addressnew;
    set address;
    count = count(fulladdress,",") + 1;
    array add[5] $30.;
    do i = 1 to dim(add);
        add[i] = scan(fulladdress,i,",");
    end;
run;

I use 5 as the dimension for the array add i used count() to find out how many component of address each row has. How I can use it as setting the dimension of the array? like array[&count] ?

According to @NEOman answer, i can use add[*] if i do not know the dimension of the array. WHile i get following error

2252      array add[*] $30. ;
ERROR: The array add has been defined with zero elements.
2253      do i = 1 to count;
2254          add[i] = scan(fulladdress,i,",");
ERROR: Too many array subscripts specified for array add.

My desired output is enter image description here

Upvotes: 2

Views: 6179

Answers (2)

Reeza
Reeza

Reputation: 21264

An array references other variables in SAS AND are not dynamic in size. The array needs to be as big or bigger than your list of elements. Each row will have the same number of variables and the last variables will be empty as necessary. You can get your code to work by looping to count variable rather than the dim of the array.

If you don't know the size of your list/array at the beginning you'll have to find it first

  *EDIT: Here's a way to find the max size of the array first;

  data _null_;
    set address end=eof;
    retain max_count 0;
    count = count(fulladdress,",") + 1;
    if count>max_count then max_count=count;
    if eof then call symputx('array_size', max_count);
  run;

 data addressnew;
  set address;
  array add[&max_count.] $30.;
  count = count(fulladdress,",") + 1;

  do i = 1 to count;
    add[i] = scan(fulladdress,i,",");
  end;
 run;

Upvotes: 2

in_user
in_user

Reputation: 1958

Use array add[*] if you are not sure about the number of elements!

OR you can define _Temporary_ array like below with dimensions greater than the number of elements, for being safe I have selected 100.

http://support.sas.com/documentation/cdl/en/lrdict/64316/HTML/default/viewer.htm#a000201956.htm

data _null_;
set address;
count = count(fulladdress,",") + 1;
put count=;
array addn{0:999} $ _temporary_;
do i = 1 to count;
    addn[i] = scan(fulladdress,i,",");
    put addn[i]=;
end;

run;

EDIT1: As I understand your problem, if the address has six segments you want to create add1-add6 variables and store the segments in them.

I tried doing it using dynamic array , but for some reason I am getting strange errors.

data addressnew;
set address;
count = count(fulladdress,",") + 1;
put count=;

array addn[*] addn: ;
do i = 1 to count;
    addn[i] = scan(fulladdress,i,",");
    put addn[i]=;
end;

Below is the TESTED code, it might not be the most sophisticated(Programming wise, but I suppose it would not have any negative impact on execution time and space wise) way to this but it is working. Hopefully someone will come up with the more simpler solution.

Selecting the maximum number of segments by scanning all the records in the entire dataset.

data temp;
set address(keep=fulladdress);
countnew = count(fulladdress,",") + 1;
run;

proc sql noprint;
select max(countnew) into: count_seg from temp;
quit;

%put &count_seg.;

/Using ARRAY/

data _null_;
set address;
count = count(fulladdress,",") + 1;
put count=;

array add{%sysfunc(compress(&count_seg.))} $30.;
do i = 1 to count;
    add[i] = scan(fulladdress,i,",");
    put add[i]=;
end;
run;

/USING MACRO/

%macro test();
data _null_;
    set address;
    countnew = count(fulladdress,",") + 1;
       %do i = 1 %to &count_seg.;
        add&i. = scan(fulladdress,&i.,",");
        put add&i.=;
    %end;
run;

%mend;
%test;

Upvotes: 2

Related Questions