BookmarkSubscribeRSS Feed
deleted_user
Not applicable
I would like to create a macro that would create a sort variable for a dotted decimal string (Chap: 1.2.3.4 or IP: 192.168.1.101) so that, for example, 1.10.1 would appear after 1.2.1 .

I was unable to find anything similar in the forums.

I can do this in Base SAS, but don't remember how to pass a data step variable into a macro.

I created the test data set with:

data test ;
input chapter $ ;
cards;
1.2.2.5
1.2.10.5
2.10
1.35
1.2.5
2.587
2.3.9.8
run ;

I created the data step version as:

data test1 ;
set test ;
array part{5} $3 ;
length chapters $19 ;
do i= 1 to countc(chapter,".")+1 ;
part(i)=scan(chapter,i);
part(i)=translate(right(part(i)),"0"," ");
chapters=trim(chapters)||"."||part(i);
end;
chapters=substr(chapters,3);
run ;

(the output gives a clearer idea of where I'm heading with this)

I created a macro that almost does what I'm looking for:

%macro multidec(string);
%local part sect padc ;
%let part=1 ;
%let sect = %scan(&string, ∂) ;
%let padc=00 ;
%let mult= ;
%do %while(§ ne );
%let sect=%substr(&padc§,%length(§)) ;
%let mult=&mult..§ ;
%let part=%eval(∂ + 1);
%let sect=%scan(&string, ∂) ;
%end;
%let mult=%substr(&mult,2) ;
%put &mult ;
%mend ;
%multidec(1.2.3.4) ;

Where I hang up is passing the value of chapter (1.2.3.4) into a macro. I'd like to pass in variable name from a dataset as well as the name of the new variable to be created, something like %multidec(chapter,chapters).

Any suggestions you'd care to offer would be welcome. Especially if someone has already done this ...
3 REPLIES 3
data_null__
Jade | Level 19
I have done this from time to time. I find it is easier to create sort variableS one for each dot so to speak. You sort by these variables and display the original.

[pre]
data test;
input chapter $;
array s[4];
length w $32;
drop w;
do _n_ = 1 to dim(s);
w = scan(chapter,_n_);
if missing(w) then leave;
s[_n_] = input(w,comma32.);
end;
cards;
1.2.2.5
1.2.10.5
2.10
1.35
1.2.5
2.587
2.3.9.8
;;;;
run;
proc sort;
by s:;
run;
proc print;
run;
[/pre]

[pre]
Obs chapter s1 s2 s3 s4

1 1.2.2.5 1 2 2 5
2 1.2.5 1 2 5 .
3 1.2.10.5 1 2 10 5
4 1.35 1 35 . .
5 2.3.9.8 2 3 9 8
6 2.10 2 10 . .
7 2.587 2 587 . .
[/pre]
deleted_user
Not applicable
Thanks _null_.

I was hoping to collapse the 'part's but thank you.

I also learned something new from your example that was quite valuable.

I did not know I could sort with a by 's:' which apparently uses all the components of the array 's'. Thanks for that.
data_null__
Jade | Level 19
You can combine the parts but then you have to have leading zeros or blanks and that gets you right back where you started.

"P:" is called a "SAS Variable Lists". There are a number of ways to specify an SVL including the nameroot followed by the colon. The SVL is very powerful. Look in the docuemention for a complete and detailed description. You can use the SVL in data steps and most procs. It is interesting to me that you can use something like P: or even _ALL_ in a DEFINE statement in PROC REPORT but you can NOT use a list of variables like "p1 p2 p3".

An array in SAS only exist in a data step. It is a fancy way to refer to a list of variables with in INDEX. A subtle difference from other programming languages but important.

Ready to join fellow brilliant minds for the SAS Hackathon?

Build your skills. Make connections. Enjoy creative freedom. Maybe change the world. Registration is now open through August 30th. Visit the SAS Hackathon homepage.

Register today!
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
  • 3 replies
  • 1210 views
  • 0 likes
  • 2 in conversation