判断两个字符串是否相似的函数 AnsiResemblesText 专题研究

//先糊涂一下
var
  b: Boolean;
begin
  b := AnsiResemblesText('abc','apc');
  ShowMessage(BoolToStr(b)); {True}

  b := AnsiResemblesText('abc','agc');
  ShowMessage(BoolToStr(b)); {False}

  b := AnsiResemblesText('abc','aac');
  ShowMessage(BoolToStr(b)); {False}

{结论: 它只认为第一对是相似的; 它到底根据什么判断的?}
end;

 
 
 
 
 

 

 
  

//我追根求源, 找到了这个函数: Soundex
var
  s: string;
begin
  s := Soundex('abc');
  ShowMessage(s);      {A120}

  s := Soundex('apc');
  ShowMessage(s);      {A120}

  s := Soundex('agc');
  ShowMessage(s);      {A200}

  s := Soundex('aac');
  ShowMessage(s);      {A200}

{结论: AnsiResemblesText 是根据 Soundex 生成的另一个字符码来比对的}
end;

 
 
 
 
 

 

 
  

//首先 Soundex 把第一个字母读出, 不区分大小写, 但用大写表示
var
  s: string;
begin
  s := Soundex('xabc');
  ShowMessage(s);      {X120}

  s := Soundex('Yabc');
  ShowMessage(s);      {Y120}

  s := Soundex('zabc');
  ShowMessage(s);      {Z120}

{结论: 如果第一个字母不同, 是绝对不会相似的}
end;

 
 
 
 
 

 

 
  

//从第2-4个字母, Soundex 为他们分别读出一个值:
//  h w               -1
//  a e i o u y       0
//  b f p v           1
//  c g j k q s x z   2
//  d t               3
//  l                 4
//  m n               5
//  r                 6
//
//不过最后把 -1 也认做 0 了; 如果字母缺失也会认做 0
begin
  ShowMessage(Soundex('Aa')); {A000}
  ShowMessage(Soundex('Ae')); {A000}
  ShowMessage(Soundex('Ai')); {A000}
  ShowMessage(Soundex('Ao')); {A000}
  ShowMessage(Soundex('Au')); {A000}
  ShowMessage(Soundex('Ay')); {A000}

  ShowMessage(Soundex('Ah')); {A000}
  ShowMessage(Soundex('Aw')); {A000}

  ShowMessage(Soundex('Ab')); {A100}
  ShowMessage(Soundex('Af')); {A100}
  ShowMessage(Soundex('Ap')); {A100}
  ShowMessage(Soundex('Av')); {A100}

  ShowMessage(Soundex('Ac')); {A200}
  ShowMessage(Soundex('Ag')); {A200}
  ShowMessage(Soundex('Aj')); {A200}
  ShowMessage(Soundex('Ak')); {A200}
  ShowMessage(Soundex('Aq')); {A200}
  ShowMessage(Soundex('As')); {A200}
  ShowMessage(Soundex('Ax')); {A200}
  ShowMessage(Soundex('Az')); {A200}

  ShowMessage(Soundex('Ad')); {A300}
  ShowMessage(Soundex('At')); {A300}

  ShowMessage(Soundex('AL')); {A400}

  ShowMessage(Soundex('Am')); {A500}
  ShowMessage(Soundex('An')); {A500}

  ShowMessage(Soundex('Ar')); {A600}

{结论: 以上只要值是一样的, 最后的结果当然是相似; 它好像是根据发音分类的}
end;

 
 
 
 
 

 

 
  

//从第2-4个字母如果不重复, 道理也就一样了
var
  b: Boolean;
begin
  {b 的编码是 1}
  ShowMessage(Soundex('Ab'));   {A100}
  ShowMessage(Soundex('Abb'));  {A100}
  ShowMessage(Soundex('Abbb')); {A100}

  {r 的编码是 6}
  ShowMessage(Soundex('Arbb')); {A610}
  ShowMessage(Soundex('Abbr')); {A160}
  ShowMessage(Soundex('Abrb')); {A161}

  {测试}
  b := AnsiResemblesText('Ab','Abbb');
  ShowMessage(BoolToStr(b)); {返回 -1, 也就是 True; 它认为 Ab 与 Abbb 是相似的}

{结论: 如果字母连续重复, 后面相同的字母将被忽略, 缺位补 0}
end;

 
 
 
 
 

 

 
  

//如果没有重复, 从第 4 个字母以后就不再计算了
var
  b: Boolean;
begin
  ShowMessage(Soundex('Abcd'));       {A123}
  ShowMessage(Soundex('Abcdbcdbcd')); {A123}

  {测试}
  b := AnsiResemblesText('Abcd','Abcdbcdbcd');
  ShowMessage(BoolToStr(b)); {True}


  {如果有重复}
  ShowMessage(Soundex('Abbbcd')); {A123}
  ShowMessage(Soundex('Abcd'));   {A123}

  {测试}
  b := AnsiResemblesText('Abbbcd','Abcd');
  ShowMessage(BoolToStr(b)); {True}

{结论:
  它只给前 4 个字母编码, 之后的忽略;
  如果第 2-4 个字母有连续的重复, 被忽略掉的字母会用后面的补齐.
}
end;

 
 
 
 
 

 

 
  

//其实 Soundex 还有一个可选参数, 它的默认值是 4
var
  b: Boolean;
begin
  ShowMessage(Soundex('Abcd', 6));    {A12300}
  ShowMessage(Soundex('Abcdbcd', 6)); {A12312}

  {测试}
  b := AnsiResemblesProc('Abcdbcd','Abcdbcd');
  ShowMessage(BoolToStr(b)); {True}

{结论:
  AnsiResemblesText 函数在使用 Soundex 时, 只是使用了默认值 4;
  也就是这个问题在 AnsiResemblesText 中并不存在;
  如果需要更复杂的比对, 直接调用 Soundex 函数就是了.

  另外, 还有一个函数 AnsiResemblesProc 和 AnsiResemblesText 是一么一样的;
  不过是后者调用了前者罢了, 无他!
}
end;

 
 
 
 
 

 

 
  

//一旦明白了, 就没有进行更多测试; 如发现不对, 万望告诉 万一 一声!

 
 
 
 
 

 

 
  

你可能感兴趣的:(判断两个字符串是否相似的函数 AnsiResemblesText 专题研究)