SAS宏:如何在不使用任何proc步骤的情况下使用SAS宏对“分隔的数字”序列进行排序?

SAS宏:如何在不使用任何proc步骤的情况下使用SAS宏对“分隔的数字”序列进行排序?,sas,Sas,以下是逗号分隔的值,如下所示: 问题是使用SAS宏语言按升序和降序对这些数字进行排序,并将它们输出到SAS日志中。 我尝试了以下代码,但无效: 我意识到这一点,因为我从未更改所创建数组中str2的值&values。所以我不能得到最终的排序结果。我知道,也许这不是唯一的原因。 有没有人能帮我改进上面的代码,或者有没有更好的方法来完成这项任务? 问题是使用SAS宏,没有过程步骤。我简化了您的逻辑 首先确定列表中的项目数,并将其指定给宏变量 使用最小函数迭代获取第n个最小值。使用%DO循环进行迭代。

以下是逗号分隔的值,如下所示:

问题是使用SAS宏语言按升序和降序对这些数字进行排序,并将它们输出到SAS日志中。 我尝试了以下代码,但无效:

我意识到这一点,因为我从未更改所创建数组中str2的值&values。所以我不能得到最终的排序结果。我知道,也许这不是唯一的原因。 有没有人能帮我改进上面的代码,或者有没有更好的方法来完成这项任务?
问题是使用SAS宏,没有过程步骤。

我简化了您的逻辑

首先确定列表中的项目数,并将其指定给宏变量 使用最小函数迭代获取第n个最小值。使用%DO循环进行迭代。 这也能正确处理领带

    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;

只是一个建议,当处理这样的代码时,首先生成伪代码或逻辑,然后创建代码。这里使用的逻辑与您在第一年编程课程中学习到的排序如何工作的逻辑类似,并且不应该在实际代码中使用。这仅用于编程练习。

将数据步骤函数字符串文字函数参数包装在%str中,而不是包装在%str中

应该是

%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));
data _null_;
  array x [10] _temporary_ (&str);
  call sortn(of x[*]);
  call symputx('list',catx(',',of x[*]));
run;
日志


问题2:这是否表明对宏的理解比预期的更深入?

在数据步骤中很容易做到。如果您知道列表中的项目数,则效果最佳。例如:

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

为什么没有数据步骤和必须是宏的限制?这样限制自己是没有效率的。不过,你还没有考虑到关系,这对初学者来说是个问题。在这里发布你认为用来排序的逻辑,或者你对代码在这里做什么的评论。我很难理解你的逻辑。
data _null_;
  array x [10] _temporary_ (&str);
  call sortn(of x[*]);
  call symputx('list',catx(',',of x[*]));
run;
%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