RANK 将给出一个字符的 ASCII 数值;所以 A=65,B=66,Z=90,a=97,z=122。
所以这应该有效(如果你只想要大写的值 - 不是 a 的不同值而不是 A):
data test;
charval='CAB';
do _t=1 to length(Charval);
numval=sum(numval,rank(char(upcase(charval),_t))-64);
end;
put _all_;
run;
另一种选择(基于下面的评论)是建立一个包含字母和值之间关系的信息。我的循环遍历每个字符 A 到 Z,然后您可以将每个字母的任何值作为标签(我只是放了 1、2、3、4 ......但 label= 会改变它)。
data fmts;
retain fmtname 'CHARNUM' type 'i';
do _t=65 to 90;
start=byte(_t); *the character, so byte(65)='A';
label=_t-64; *the resulting number;
output;
end;
run;
proc format cntlin=fmts;
quit;
data test;
charval='CAB';
do _t=1 to length(Charval);
numval=sum(numval,input(char(upcase(charval),_t),CHARNUM.));
end;
put _all_;
run;
最后,如果您希望能够在同一个数据步中构造它,您可以在哈希表中构造关系并查找结果。如果需要,我可以解释一下,尽管我希望看到一个更详细的示例,说明您在定义字母与其代码之间的关系方面想要做什么。
如果您需要查看中间值,您可以通过在循环中插入 CAT 函数来实现 - 我推荐 CATX:
data test;
charval='CAB';
format intermed $100.;
do _t=1 to length(Charval);
numval=sum(numval,input(char(upcase(charval),_t),CHARNUM.));
intermed=catx('|',intermed,input(char(upcase(charval),_t),CHARNUM.)); *or the RANK portion from earlier;
end;
put _all_;
run;
这会给你3|1|2
,然后你可以通过 SCAN 进行数学运算:
do _t = 1 to countc(intermed,'|')+1;
numval2 = sum(numval2,scan(intermed,_t,'|'));
end;