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;
另一个选项(基于下面的 cmets)是建立一个包含字母和值之间关系的信息。我的循环遍历每个字符 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;
最后,如果您希望能够在 same 数据步中构造它,您可以在哈希表中构造关系并查找结果。如果需要,我可以解释一下,不过我希望看到一个更详细的示例,说明您在定义字母与其代码之间的关系方面想要做什么。
如果您需要查看中间值,可以通过在循环中插入 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;