1

是否可以对部分子字符串进行 SAS 哈希查找?

所以哈希表键将包含:'LongString' 但我的目标表键有:'LongStr'

(目标表键字符串长度可能不同)

4

2 回答 2

2

你可以,但它并不漂亮,而且你可能无法获得你正在寻找的性能优势。此外,根据字符串的长度和表格的大小,您可能无法将所有哈希表元素放入内存中。

诀窍是首先生成所有可能的子字符串,然后在哈希表上使用“多数据”选项。

创建一个包含我们要匹配的单词的数据集:

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 提供的一些示例数据。

于 2012-09-10T14:04:07.547 回答
1

您必须使用 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;
于 2012-09-10T13:18:21.740 回答