我有一个变量,其中包含我将要用于进程的单词列表,并且需要保留在一个变量中(至少,在此问题/答案结束时需要返回在一个变量)。我需要对要删除重复的单词列表。
对变量进行重复数据删除的最有效方法是什么?我可以不将变量拆分成多个变量吗?
例如,我有这个数据集:
data want;
x = "A B C D E F G H I J K";
run;
我希望返回此数据集。
data want;
set have;
array myvar /* the variables I do not have*/ ;
call sortc(of myvar[*]);
run;
如果我有多个变量,我可以这样做
call scan
但是这不仅仅适用于一个变量,而是对该变量中的单词进行排序。
实际字符串的长度可能超过一个字符,如果相关(请不要提供仅适用于一个字符的解决方案)。单词不需要按任何特定的顺序排序,你删除的副本是无关紧要的 - " C F E G H I A B D J K"和" A B C D E F G H I J K"同样有效。或任何其他组合。
答案 0 :(得分:3)
只需添加新列表中尚未包含的每个单词,即可构建新列表。如果需要,可以指定要在函数调用中使用的分隔符列表。
data have;
old = 'A B C D E F E G H B I A B D J K';
run;
data want ;
set have;
length word new $200 ;
do i=1 to countw(old);
word=scan(old,i);
if indexw(new,word) then continue;
new=catx(' ',new,word);
end;
put (old new) (=/);
run;
old=A B C D E F E G H B I A B D J K
new=A B C D E F G H I J K
答案 1 :(得分:1)
此问题的一个解决方案包括使用findw
迭代单词,并使用data have;
x = "A B C D E F E G H B I A B D J K"; *initialize dataset;
do count = countw(x) to 2 by -1; *iterate over words (right to left here);
call scan(x,count,position,length); *look for the first word;
_curword = substr(x,position,length); *for simplicity, I make a temporary variable with the current word and the current rest of string. This could be done without these two variables just including them in the `findw` itself.;
_restofstring = substr(x,1,position-1); *The remaining (to the left) portion of the string that could have duplicates;
put "|"_curword "|"_restofstring "|";
put position= length=;
if findw(_restofstring,trim(_curword)) then do; *If a duplicate is found;
put "Deleting" _curword=; *delete it below;
x = substr(x,1,position-1) || substr(x,position+length+1);
end;
end;
put x=;
run;
将其与剩余的子字符串进行比较,以删除重复项。
flexslider
答案 2 :(得分:1)
您可以将每个单词输出到单独的记录中,对其进行排序&删除重复项,然后展平回到单个记录。
data have ; x = "A B C D E F E G H B I A B D J K" ; id = _n_ ; do i = 1 to countw(x) ; word = scan(x,i,' ') ; output ; end ; run ; proc sort data=have nodupkey ; by id word ; run ; data want ; set have ; by id ; length x $200. ; /* same length as 'x' in have dataset */ retain x '' ; if first.id then call missing(x) ; x = catx(' ',x,word) ; if last.id then output ; run ;
你可以利用proc fcmp
和宏的力量创建一个宏功能三明治,从而进一步发展这个阶段:
proc fcmp outlib=work.funcs.utility ; function dedupe(string $) $ ; length string $200 ; rc = run_macro('DEDUPE',string) ; /* call dedupe macro */ if rc = 0 then return(strip(string)) ; else return('') ; endsub ; quit ; options cmplib=work.funcs ; %MACRO DEDUPE ; data __dedupe ; x = &STRING ; /* passed from proc fcmp with quotes */ do i = 1 to countw(x) ; word = scan(x,i,' ') ; output ; end ; run ; proc sort data=__dedupe nodupkey ; by word ; run ; data _null_ ; set __dedupe end=eof ; length x $200 ; retain x '' ; x = catx(' ',x,word) ; if eof then call symput('STRING',strip(x)) ; /* return &STRING to proc fcmp */ run ; /* cleanup */ proc sql noprint ; drop table __dedupe ; quit ; %MEND ;
一旦定义,您就可以像使用任何其他datastep函数一样使用它。在PROC FCMP中调用的宏的美妙之处在于它们独立于“on-the-side”运行,远离调用该函数的datastep。
data want ; x = "A B C D E F E G H B I A B D J K" ; x2 = dedupe(x) ; run ;
然后您可以将FCMP函数包装在另一个宏中,并在%SYSFUNC
内调用该函数,这样您就可以对宏变量执行相同的处理:
%MACRO STRDEDUPE(STR) ; %SYSFUNC(dedupe(&STR)) %MEND ; %LET X = A B C D E F E G H B I A B D J K ; %PUT %STRDEDUPE(&X) ;
PROC FCMP程序> https://support.sas.com/documentation/cdl/en/proc/61895/HTML/default/viewer.htm#a002890483.htm
在功能型宏中使用SAS®的全功能(SUGI Paper,2012)> https://support.sas.com/resources/papers/proceedings12/004-2012.pdf
[未经测试的代码,如果有任何错误,请告诉我们]
答案 3 :(得分:0)
data have;
x = "A B C D E F E G H B I A B D J K";
do i=1 to countw(x);
_x=prxchange('s/(\b\w+?\b)(.*?)(?=\1{1,})(.?)/$2 $3/i',-1,x);
x=_x;
end;
drop i;
run;
proc print;
run;