是否可以对部分子字符串进行 SAS 哈希查找?
所以哈希表键将包含:'LongString' 但我的目标表键有:'LongStr'
(目标表键字符串长度可能不同)
你可以,但它并不漂亮,而且你可能无法获得你正在寻找的性能优势。此外,根据字符串的长度和表格的大小,您可能无法将所有哈希表元素放入内存中。
诀窍是首先生成所有可能的子字符串,然后在哈希表上使用“多数据”选项。
创建一个包含我们要匹配的单词的数据集:
data keys;
length key $10 value $1;
input key;
cards;
LongString
LongOther
;
run;
生成所有可能的子串:
data abbreviations;
length abbrev $10;
set keys;
do cnt=1 to length(key);
abbrev = substr(key,1,cnt);
output;
end;
run;
创建一个包含我们要搜索的术语的数据集:
data match_attempts;
length abbrev $10;
input abbrev ;
cards;
L
Long
LongO
LongSt
LongOther
;
run;
执行查找:
data match;
length abbrev key $10;
set match_attempts;
if _n_ = 1 then do;
declare hash h1(dataset:'abbreviations', multidata: 'y');
h1.defineKey('abbrev');
h1.defineData('abbrev', 'key');
h1.defineDone();
call missing(abbrev, key);
end;
if h1.find() eq 0 then do;
output;
h1.has_next(result: r);
do while(r ne 0);
h1.find_next();
output;
h1.has_next(result: r);
end;
end;
drop r;
run;
输出(注意 'Long' 如何返回 2 个匹配项):
Obs abbrev key
=== ========= ==========
1 Long LongString
2 Long LongOther
3 LongO LongOther
4 LongSt LongString
5 LongOther LongOther
还有一些笔记。散列表不支持like
运算符之类的原因是因为它在将记录插入散列表之前对键进行“散列”。执行查找时,要查找的值是“散列”,然后对散列值执行匹配。当一个值被散列时,即使值的微小变化也会产生完全不同的结果。以下面的例子为例,散列 2 个几乎相同的字符串会产生 2 个完全不同的值:
data _null_;
length hashed_value $16;
hashed_value = md5("String");
put hashed_value= hex32.;
hashed_value = md5("String1");
put hashed_value= hex32.;
run;
输出:
hashed_value=27118326006D3829667A400AD23D5D98
hashed_value=0EAB2ADFFF8C9A250BBE72D5BEA16E29
因此,哈希表不能使用like
运算符。
最后,感谢@vasja 提供的一些示例数据。
您必须使用 Iterator 对象循环遍历键并自己进行匹配。
data keys;
length key $10 value $1;
input key value;
cards;
LongString A
LongOther B
;
run;
proc sort data=keys;
by key;
run;
data data;
length short_key $10;
input short_key ;
cards;
LongStr
LongSt
LongOther
LongOth
LongOt
LongO
LongSt
LongOther
;
run;
data match;
set data;
length key $20 outvalue value $1;
drop key value rc;
if _N_ = 1 then do;
call missing(key, value);
declare hash h1(dataset:"work.keys", ordered: 'yes');
declare hiter iter ('h1');
h1.defineKey('key');
h1.defineData('key', 'value');
h1.defineDone();
end;
rc = iter.first();/* reset to beginning */
do while (rc = 0);/* loop through the long keys and find a match */
if index(key, trim(short_key)) > 0 then do;
outvalue = value;
iter.last(); /* leave after match */
end;
rc = iter.next();
end;
run;