Макрос SAS: как отсортировать последовательность чисел, разделенных «,», с помощью макроса SAS без использования каких-либо шагов pro c? - PullRequest
0 голосов
/ 21 июня 2020

Вот значения, разделенные запятыми:

15,30,16,8,86,98,6

Вопрос заключается в использовании макроязыка SAS для сортировки этих чисел по возрастанию и убыванию и вывода их в журнал SAS . Я попробовал следующий код, но он не сработал:

%macro sorts (values=);
%let val = %sysfunc(countw(&values.,','));
%do i=1 %to &val.;
    %let str1= %scan(&values.,&i.,',');
        %do j=&i.+1 %to &val.;
             %let seq = %bquote( );
             
            %let str2= %scan(&values.,&j.,',');
            %if &str1. < &str2. %then %do;
                %let tmp = &str1.;
                %let str1 = &str2.;
                %let str2 = &tmp.;
                %let seq = &str1.;
         %end;
         %put &str1.;
  %end;
%end;

%mend sorts;

%sorts(values=%str(15,30,16,8,86,98,6));

Я понял это, потому что я никогда не менял значение str2 в созданном массиве & values. , так что я не могу получить окончательные отсортированные результаты. Знаю, может, это не единственная причина. Может ли кто-нибудь быть настолько любезным, чтобы помочь мне улучшить этот код, приведенный выше, или есть лучший способ выполнить sh эту задачу? Вопрос: с использованием макроса SAS, без про c шагов.

Ответы [ 3 ]

3 голосов
/ 22 июня 2020

Обернуть аргументы функции строкового литерала функции шага DATA в %str() вместо ''

%let val = %sysfunc(countw(&values.,','));

Должно быть

%let val = %sysfunc(countw(&values.,%str(,)));

Лично, если бы это было присвоение, я слегка ткнул бы профессору в глаза и использовал бы SORTN процедуру вызова.

Пример:

%macro sortn (values=);
  %local nvalues i args comma;
  %let nvalues = %sysfunc(countw(&values.,%str(,)));
  %do i=1 %to &nvalues;
    %local x&i;
    %let x&i = %scan(&values.,&i.,%str(,));
    %let args = &args &comma x&i;
    %Let comma = ,;
  %end;
  %let comma =;

  %syscall sortn(&args);

  %do i = 1 %to &nvalues;%superq(comma)%superq(x&i) 
    %let comma=,;
  %end;
%mend sortn;

%put %sortn(values=%str(15,30,16,8,86,98,6,1));

LOG

575  %put %sortn(values=%str(15,30,16,8,86,98,6,1));
1,6,8,15,16,30,86,98

Q2: Это показывает более глубокое понимание макроса, чем предполагалось?

2 голосов
/ 22 июня 2020

Это достаточно просто сделать в шаге данных. Лучше всего работает, если вы знаете количество элементов в списке. Пример:

data _null_;
  array x [10] _temporary_ (&str);
  call sortn(of x[*]);
  call symputx('list',catx(',',of x[*]));
run;

Итак, чтобы преобразовать это в макрос, просто воспользуйтесь преимуществами опции SYSPARM и функции DOSUBL ().

%macro sort() / parmbuff ;
%local n rc list ;
%let n=%sysfunc(countw(&syspbuff,( , )));
%if &n %then %do;
  %let rc=%sysfunc(dosubl(%qsysfunc(dequote("
data _null_;
  array x [&n] _temporary_ &syspbuff;
  call sortn(of x[*]);
  call symputx('list',catx(',',of x[*]));
run;
"))));
  %*;&list
%end;
%mend sort;

Пример использования:

174   %put %sort(15, 30, 16, 8, 86, 98, 6, 6, 100, -9);
NOTE: DATA statement used (Total process time):
      real time           0.00 seconds
      cpu time            0.00 seconds


-9,6,6,8,15,16,30,86,98,100
175   %put %sort(5 6 3 10);
NOTE: DATA statement used (Total process time):
      real time           0.00 seconds
      cpu time            0.00 seconds


3,5,6,10
2 голосов
/ 22 июня 2020

Я упростил ваш лог c.

  1. Сначала определите количество элементов в вашем списке и назначьте его макрос-переменной
  2. Используйте функцию НАИМЕНЬШИЙ () для итеративно получить n-е наименьшее значение. Используйте% DO l oop для итерации.

Это также правильно обрабатывает связи.

    options mprint symbolgen;
    %let str = 15, 30, 16, 8, 86, 98, 6, 6, 100, -9;
    %let new_list = ;
    
    %macro sort(list=);
        %let nWords = %sysfunc(countw(&list.));
        %global new_list;
        %let new_list = %sysfunc(smallest(1, %unquote(&list)));
            
        %do i=2 %to &nwords;
            %let element = %sysfunc(smallest(&i, %unquote(&list)));
            %let new_list = &new_list, &element;
        %end;
        
    %mend;
    
    %sort(list=%quote(&str));
    
    %put &new_list;

Просто предложение, при работе с таким кодом сначала сгенерируйте псевдокод или ваш лог c, а затем создайте код. Используемый здесь logi c аналогичен тому, что вы узнали бы на первом курсе программирования о том, как работают сортировки, и НИКОГДА не должны использоваться в реальном коде. Это полезно исключительно в качестве упражнения по программированию.

...