Advertisement
heroijapa

Geocodex

Oct 16th, 2014
127
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Delphi 26.25 KB | None | 0 0
  1. http://www.devmedia.com.br/forum/soundex-em-portugues/274192
  2.  
  3. http://sourceforge.net/p/metaphoneptbr/code/ci/master/tree/README
  4.  
  5. https://code.launchpad.net/metaphoneptbr
  6.  
  7.  
  8. SOUNDEX EM PORTUGUÊS!!
  9.  
  10. José Henrique
  11. Caros colegas
  12. Fiz um sistema de cadastro de pacientes para um setor de hospital e precisava que a ficha dos pacientes fossem recuperadas pelo nome independentemente das muitas grafias com que podem ser escritos. Exemplo: Tereza, Theresa, etc.
  13. Durante muito tempo procurei um rotina que convertesse uma palavra para os fonemas que a compõe, e sempre fui remetido ao Soundex que funciona para o idioma inglês, mas não para o nosso português.
  14. Em minhas andanças pela net achei a tese de mestrado “Desenvolvimento de Sistema para Conversão de Textos em Fonemas no Idioma Português”, de Dimas Trevizan Chbane (neste [url=http://regulus.pcs.usp.br/~geraldo/textos/disdimas.pdf]endereço[/url], o trabalho é extenso e permitiria até fazer um sistema de fala e de separação de sílabas.) e com base nele fiz uma rotina que devolve os fonemas.
  15. Agora, gostaria que vocês analisassem a rotina e fizessem sugestões visando a melhoria.
  16.  
  17. Vejam alguns resultados
  18. [list:47c3a064a7]
  19. ANDREA andRea
  20. ANDREIA andRea
  21. ELENAelena
  22. HELENAelena
  23. ELIZABETE elizabete
  24. ELIZABETH elizabete
  25. ELISABETE elizabete
  26. INACIOesxetian
  27. IGNACIOinasiu
  28. GIZELLE jizele
  29. GIZELEjizele
  30. GISELLE jizele
  31. GISELEjizele
  32. GISELI jizeli
  33. GISELLI jizeli
  34. KELY keli
  35. QUELI keli
  36. KELLY keli
  37. KELLI keli
  38. KELI keli
  39. CRISTINA kRistina
  40. CRISTINAkristina
  41. LOPEZlopes
  42. LOPESlopes
  43. MARTAmaRta
  44. MARTHA maRta
  45. OSVALDOosvaudu
  46. OSWALDOosvaudu
  47. RUTErute
  48. RUTHrute
  49. SIDNEYsidinei
  50. SYDNEYsidinei
  51. SIDNEIsidinei
  52. SYDNEIsidinei
  53. CYDNEIsidinei
  54. CYDNEYsidinei
  55. CIDNEIsidinei
  56. SYLVIA siuvia
  57. SILVIA siuvia
  58. TERESA teReza
  59. THEREZAteReza
  60. THERESAteReza
  61. TEREZA teReza
  62. WALKIRIA vaukiRia
  63. WALQUIRIA vaukiRia
  64. VALQUIRIAvaukiRia
  65. CHEILAxeila
  66. SHEILAxeila
  67. [/list:u:47c3a064a7]
  68.  
  69.  
  70. #Código
  71.  
  72. function SomDex (strNome : string) : string;
  73. var
  74.   V, V1 : set of Char;
  75.   C, CN : set of ´a´..´z´;
  76.  
  77.   intTam, n : integer;
  78.  
  79. begin
  80.   V := [´a´, ´e´, ´i´, ´o´, ´u´, ´y´, ´á´,´é´, ´ê´, ´ó´, ´ô´, ´í´, ´ú´, ´â´, ´à´, ´ä´, ´è´, ´ë´, ´ì´, ´ï´, ´î´, ´ò´, ´ö´, ´ü´, ´ù´, ´û´];
  81.   V1 := [´e´, ´i´, ´y´,´é´, ´ê´, ´í´, ´è´, ´ë´, ´ì´, ´ï´, ´î´, ´ù´, ´û´];
  82.   C := [´b´, ´c´, ´d´, ´f´, ´g´, ´h´, ´j´, ´k´, ´l´, ´m´, ´n´, ´p´, ´q´, ´r´, ´s´, ´t´, ´v´, ´w´, ´x´, ´z´];
  83.   CN := [´m´, ´n´];
  84.  
  85.   {Result := Excecoes.Values[Trim(strNome)];
  86.   if Result <> ´´ then exit;}
  87.   Result := ´´;
  88.   strNome := ´´ + AnsiLowerCase(Trim(strNome)) + ´´;
  89.   intTam := length(strNome);
  90.   n := 1;
  91.   while n < intTam do
  92.   begin
  93.     inc(n);
  94.     if (strNome[n] = strNome[n + 1]) then
  95.        inc(n);
  96.        
  97.     case strNome[n] of
  98.        ´´ :
  99.            exit;
  100.        ´a´, ´á´, ´â´, ´à´, ´ä´ :
  101.            Result := Result + ´a´;
  102.        ´e´, ´è´, ´ë´ :
  103.            begin
  104.              if (strNome[n + 1]= ´´) or (Copy(strNome, n+1, 2) = ´s´) then
  105.                 Result := Result + ´e´
  106.                 //Result := Result + ´i´
  107.              else
  108.                 Result := Result + ´e´;
  109.            end;
  110.        ´é´, ´ê´ :
  111.            Result := Result + ´e´;
  112.        ´i´, ´y´, ´í´, ´ì´, ´ï´, ´î´ :
  113.              if not ((strNome[n - 1] in [´e´, ´é´]) and (strNome[n + 1] in [´a´, ´o´])) then
  114.                 Result := Result + ´i´;
  115.        ´o´, ´ò´, ´ö´ :
  116.            begin
  117.              if (strNome[n+1] = ´´) or (Copy(strNome, n+1, 2) = ´s´) then
  118.                 Result := Result + ´u´
  119.              else
  120.                 Result := Result + ´o´;
  121.            end;
  122.        ´ó´, ´ô´ :
  123.            begin
  124.              if (strNome[n+1] = ´´) then
  125.                 Result := Result + ´o´
  126.              else
  127.                 Result := Result + ´o´;
  128.            end;
  129.        ´u´, ´ú´, ´ü´, ´ù´, ´û´ :
  130.            Result := Result + ´u´;
  131.        ´b´, ´f´, ´j´, ´k´, ´v´  :
  132.            Result := Result + strNome[n];
  133.        ´c´ :
  134.            begin
  135.              if (strNome[n+1] in V1) then
  136.                 Result := Result + ´s´
  137.              else if (strNome[n+1] in [´a´, ´o´, ´u´, ´r´, ´l´]) then
  138.                 Result := Result + ´k´
  139.              else if (Copy(strNome, n + 1, 2) = ´hr´) then  //christina, chrizóstemo
  140.                begin
  141.                   Result := Result + ´kR´;
  142.                   n := n + 2;
  143.                end
  144.              else if (strNome[n+1] = ´h´) then
  145.                begin
  146.                   Result := Result + ´x´;
  147.                   inc(n);
  148.                end
  149.              else if (strNome[n+1] = ´k´) then
  150.                begin
  151.                   Result := Result + ´k´;
  152.                   inc(n);
  153.                end
  154.              else
  155.                 Result := Result + ´k´;
  156.            end;
  157.        ´d´ :
  158.            begin
  159.              if (strNome[n+1] in C) and (not (strNome[n+1] in [´r´, ´l´])) or (strNome[n+1] = ´´) then
  160.                 Result := Result + ´di´
  161.              else
  162.                 Result := Result + ´d´;
  163.            end;
  164.        ´g´ :
  165.            begin
  166.              if (Copy(strNome, n + 1, 2) = ´ue´) or (Copy(strNome, n + 1, 2) = ´ui´) or(strNome[n+1] = ´ü´) then
  167.                begin
  168.                  Result := Result + ´g´;
  169.                  inc(n);
  170.                end
  171.              else if (strNome[n+1] in [´i´, ´e´]) then
  172.                 Result := Result + ´j´
  173.              else if (Copy(strNome, n - 2, 2) = ´i´) and (strNome[n + 1] = ´n´) then
  174.                begin
  175.                  Result := Result + ´n´;
  176.                  inc(n);
  177.                end
  178.              else
  179.                Result := Result + ´g´;
  180.            end;
  181.        ´h´ :
  182.            n := n;
  183.        ´l´ :
  184.            begin
  185.              if (strNome[n+1] = ´h´) then
  186.                begin
  187.                  Result := Result + ´L´;
  188.                  inc(n);
  189.                end
  190.              else if (strNome[n+1] = ´´) then
  191.                 Result := Result + ´u´
  192.              else if (strNome[n+1] in C) then
  193.                 Result := Result + ´u´
  194.              else
  195.                 Result := Result + ´l´
  196.            end;
  197.        ´m´ :
  198.            begin
  199.              if (strNome[n-1] in V) and  (strNome[n+1] in C) or (strNome[n+1] = ´´) then
  200.                 Result := Result + ´n´
  201.              else
  202.                 Result := Result + ´m´;
  203.            end;
  204.        ´n´ :
  205.            begin
  206.              if (strNome[n+1] = ´h´) then
  207.                begin
  208.                  Result := Result + ´N´;
  209.                  inc(n);
  210.                end
  211.              else
  212.                 Result := Result + ´n´
  213.            end;
  214.        ´p´ :
  215.            begin
  216.              if (strNome[n+1] = ´h´) then
  217.                begin
  218.                  Result := Result + ´f´;
  219.                  inc(n);
  220.                end
  221.              else
  222.                 Result := Result + ´p´;
  223.            end;
  224.        ´q´ :
  225.            begin
  226.              if (Copy(strNome, n + 1, 2) = ´ue´) or (Copy(strNome, n + 1, 2) = ´ui´) then
  227.                begin
  228.                  Result := Result + ´k´;
  229.                  inc(n);
  230.                end
  231.              else
  232.                  Result := Result + ´k´;
  233.            end;
  234.        ´r´ :
  235.            begin
  236.              if (strNome[n-1] in  [´´, ´n´, ´m´, ´r´]) then
  237.                 Result := Result + ´r´
  238.              else
  239.                 Result := Result + ´R´
  240.            end;
  241.        ´s´ :
  242.            begin
  243.              if (strNome[n+1] = ´h´) then
  244.                begin
  245.                   Result := Result + ´x´;
  246.                   inc(n);
  247.                end
  248.              else if (strNome[n-1] = ´´) and (strNome[n+1] in V) then
  249.                  Result := Result + ´s´
  250.              else if (strNome[n-1] = ´´) and (strNome[n+1] in C) then
  251.                  Result := Result + ´es´
  252.              else if (Copy(strNome, n + 1, 2) = ´ce´) or (Copy(strNome, n + 1, 2) = ´ci´) or (strNome[n+1] = ´ç´) then
  253.                begin
  254.                   Result := Result + ´s´;
  255.                   inc(n);
  256.                end
  257.              else if (strNome[n-1] in V) and (strNome[n+1] in V) then
  258.                   Result := Result + ´z´
  259.              else if (strNome[n-1] in V) and (strNome[n+1] in C) then
  260.                   Result := Result + ´s´
  261.              else if (Copy(strNome, 1, 3) = ´ex´) and (strNome[n-1] in V) then
  262.                  Result := Result + ´z´
  263.              else if (strNome[n-1] in C) and  (strNome[n+1] in V) then
  264.                   Result := Result + ´s´
  265.              else
  266.                 Result := Result + ´s´;
  267.            end;
  268.        ´t´ :
  269.            begin
  270.              if (Copy(strNome, n + 1, 2) = ´h#´) then
  271.                 Result := Result + ´te´
  272.              else if (strNome[n+1] <> ´´) then
  273.                 Result := Result + ´t´;
  274.            end;
  275.        ´w´ :
  276.            begin
  277.              if (Copy(strNome, n + 1, 2) = ´al´) or (Copy(strNome, n + 1, 2) = ´an´) then
  278.                 Result := Result + ´v´
  279.              else
  280.                 Result := Result + ´u´;
  281.            end;
  282.        ´x´ :
  283.            begin
  284.              if (strNome[n-1] = ´´) or (strNome[n-1] = ´n´) then
  285.                  Result := Result + ´x´
  286.              else if (Copy(strNome, n+1, 2) = ´ce´) or (Copy(strNome, n+1, 2) = ´ci´) then
  287.                begin
  288.                  Result := Result + ´s´;
  289.                  inc(n);
  290.                end
  291.              else if (strNome[n-1] in V) and (strNome[n+1] = ´t´) then
  292.                  Result := Result + ´s´
  293.              else if (Copy(strNome, n+1, 2) = ´ai´) or (Copy(strNome, n+1, 2) = ´ei´) or (Copy(strNome, n+1, 2) = ´ou´) then
  294.                  Result := Result + ´x´
  295.              else if (Copy(strNome, n- 2, 2) = ´e´) and  (strNome[n+1] in V) then
  296.                  Result := Result + ´z´
  297.              else
  298.                  Result := Result + ´x´
  299.            end;
  300.        ´z´ :
  301.            begin
  302.              if (strNome[n-1] = ´´) then
  303.                  Result := Result + ´z´
  304.              else if (strNome[n+1] = ´´) or (strNome[n+1] in C) then
  305.                  Result := Result + ´s´
  306.              else
  307.                   Result := Result + ´z´
  308.            end;
  309.        ´ç´ :
  310.            Result := Result + ´s´;
  311.        ´ã´ :
  312.                 Result := Result + ´ã´;
  313.        ´õ´ :
  314.            Result := Result + ´õ´;
  315.         ´´´´ : inc(n);
  316.        else
  317.           Result := Result + ´@´;
  318.     end;
  319.   end;
  320. end;
  321.  
  322.  
  323. Lógico que existem limitações e gostaria que opinassem dessem sugestões:
  324. 1 - A rotina foi feita funciona com o portugûes portanto pode falhar com nomes estrangeiros como Washington, William, Rachel, etc. largamente utilizados. Mas resolvi isso com um dicionário (está comentado no código, já que não é o principal aqui) Fiz algumas adaptações como converter ´sh´ por ´x´ embora ´sh´ não faça parte do português.
  325. 2 - Gostaria que os nomes terminados em ´e´ e ´i´ retornassem com a mesma letra no final Gergete, Gerogeti = georgeti, mas isso causa problemas como outros nomes como Jose (sem acento) que viria como josi. Os que terminam com ´o´ vem com ´u´. Augusto, Augustu = augustu
  326. 3 - O ´s´ no final é eliminado. Marcos, Marco, Marcus = marcu
  327.  
  328. Abaixo transcrevo as regras publicadas na tese sobre como conversão de palvras em seus fonemas:
  329. ´Arquivo REGRAS.CON
  330. Para a descrição das regras do arquivo REGRAS.CON foram utilizados
  331. alguns caracteres especiais com a finalidade de simplificar as regras a serem
  332. aplicadas. Assim, o símbolo # serve como delimitador de palavras; o símbolo $
  333. como indicador de qualquer uma das vogais; o símbolo * como indicador de
  334. qualquer uma das consoantes e o símbolo ¬ como indicador das consoantes nasais
  335. (m ou n).
  336. As linha iniciadas por ponto-e-vírgula (;) são consideradas comentários, e
  337. linhas em branco não são consideradas. Para cada letra deve existir um conjunto de
  338. regras separadas por barra (/), no seguinte formato:
  339. /letra, fone_default, incremento
  340. regra 1
  341. ...
  342. regra n
  343. /
  344. sendo que:
  345. - letra corresponde a letra a ser convertida;
  346. - fone_default é o fonema que deve ser substituido caso o contexto não se encaixe
  347. em nenhuma das regras descritas abaixo, e
  348. - incremento é a quantidade que deve ser adicionada ao indexador de letras da
  349. palavra. Quando incremento = 1, significa que se deve analisar a
  350. próxima letra da palavra; incremento = 2, significa que se deve
  351. ´pular´ a próxima letra e considerar a seguinte.
  352. No caso da letra ´b´, por exemplo, não há regras especiais de conversão,
  353. tornando essa definição como simplesmente:
  354. /b,b,1
  355. /
  356. Caso haja alguma regra de conversão, sua especificação deve ser feita após a
  357. primeira linha contendo barra (/), no seguinte formato:
  358. carac_anterior, carac_posterior, fone, incremento, tônica
  359. onde:
  360. - carac_anterior são os caracteres (ou caracter) que precedem a letra considerada;
  361. - carac_posterior são os caracteres (ou caracter) que sucedem a letra
  362. considerada;
  363. - fone é transcrição fonológica, constituida por apenas um caracter, a ser aplicada
  364. caso os caracteres que precedem e sucedem a letra sejam os mesmos de
  365. carac-anterior e carac_posterior;
  366. - incremento é definido de maneira análoga à do fone_default, e
  367. - tônica indica a necessidade da aplicação da regra, no caso de letra pertencente à
  368. silaba tônica.
  369. Para a letra ´c´, por exemplo, essas regras seriam:
  370. /c,k,1
  371. ,e,s,1,
  372. ,i,s,1,
  373. ,a,k,1,
  374. ,o,k,1,
  375. ,u,k,1,
  376. ,h,x,2,
  377. /
  378.  
  379. Neste caso não há contexto anterior à letra ´c´. Havendo as letras ´e´ ou ´i´
  380. após a letra ´c´´, sua transcrição corresponderá à /s/; caso seja seguida por ´a´, ´o´ ou
  381. ´u´, a transcrição corresponderá à /k/, e se for seguida por ´h´, será transcrita para
  382. /x/, e a letra ´h´ será ´pulada´ (incremento = 2). Não há exigências para que essas
  383. letras façam parte da sílaba tônica, em nenhuma dessas regras.
  384. Para a letra ´a´, a terceira regra indicada abaixo apenas deverá ser aplicada
  385. quando esta letra pertencer à sílaba tônica:
  386. /a,a,1
  387. ,¬*,ã,2,
  388. ,¬#,Ã,2,
  389. ,¬,ã,2,t
  390. /
  391. Conforme essa regra, o ´a´ seguido de consoante nasal deve ser transcrito
  392. para /ã/ quando pertencer à sílaba tônica. Deverá igualmente ser transcrito para /ã/
  393. quando seguido de consoante nasal e depois por consoante (1 a . regra), e para /Ã/,
  394. representando /ãu/, quando seguido por consoante nasal em final de palavra (2 a .
  395. regra).
  396. As demais regras utilizadas estão descritas no Anexo A, utilizando-se o
  397. alfabéto fonético de um caracter apresentado na Tabela 2.1, com os seguintes
  398. caracteres adicionais:
  399. - a letra ´E´, para designar o encontro vocálico ´ei´ que ocorre em palavras
  400. terminadas por ´em´, como na palavra sem (/seim/), transcrita como /sEm/.
  401. - a letra ´Ã´, para designar o encontro vocálico ´ãu´ que ocorre em palavras
  402. terminadas por ´am´, como na palavra falam (/falãu/), transcrita como /falÃ/.
  403. - a letra ´K´, para designar a transcrição /ks/ para a letra ´x´, que ocorre em
  404. palavras como fixo (/fikso/), transcrita como /fiKo/.
  405.  
  406.  
  407. REGRAS DE CONVERSÃO ARQUIVO REGRAS.CON
  408. ; Simbolos utilizados
  409. ;
  410. ; # - delimitador de palavra
  411. ; $ - vogais
  412. ; * - consoante
  413. ; ¬ - m ou n
  414. ;
  415.  
  416. /a,a,1
  417. ,¬*,ã,2,
  418. ,¬,Ã,2,
  419. ,¬,ã,2,t
  420. /
  421. /b,b,1
  422. /
  423. /c,k,1
  424. ,e,s,1,
  425. ,ê,s,1,
  426. ,é,s,1,
  427. ,i,s,1,
  428. ,í,s,1,
  429. ,a,k,1,
  430. ,o,k,1,
  431. ,u,k,1,
  432. ,h,x,2,
  433. /
  434. /d,d,1
  435. /
  436. /e,e,1
  437. ,¬,E,1,
  438. /
  439. /f,f,1
  440. /
  441. /g,g,1
  442. ,ue,g,2,
  443. ,,g,2,
  444. ,ui,g,2,
  445. ,i,j,1,
  446. ,e,j,1,
  447. ,ü,g,1,
  448. /
  449. /h,,1
  450. ,,,1,
  451. ,,,1,
  452. /
  453. /i,i,1
  454. /
  455. /j,j,1
  456. /
  457. /k,k,1
  458. /
  459. /l,l,1
  460. ,h,L,2,
  461. ,*,|,1,
  462. ,,|,1,
  463. /
  464. /m,m,1
  465. /
  466. /n,n,1
  467. ,h,N,2,
  468. /
  469. /o,o,1
  470. ,so,o,1,
  471. ,sa#,ó,1,
  472. /
  473. /p,p,1
  474. /
  475. /q,k,1
  476. ,ua,k,1,
  477. ,,k,1
  478. ,ue,k,2,
  479. ,,k,2
  480. ,ui,k,2,
  481. ,uo,k,1,
  482. ,,k,1
  483. ,ü,k,1
  484. /
  485. /r,r,1
  486. ,,R,1,
  487. ,r,,1,
  488. r,,R,1,
  489. ,*,h,1,
  490. ,,h,1,
  491. /
  492. /s,s,1
  493. ,,s,1,
  494. ,,s,1,
  495. ,ce,,1,
  496. ,ci,,1,
  497. ,ç,,1,
  498. $,$,z,1,
  499. ,s,,1,
  500. s,,s,1,
  501. $,*,s,1,
  502. ex,$,z,1,
  503. *,$,s,1,
  504. /
  505. /t,t,1
  506. ,h,t,2,
  507. /
  508. /u,u,1
  509. /
  510. /v,v,1
  511. /
  512. /w,w,1
  513. /
  514. /x,x,1
  515. ,,x,1,
  516. ,ce,,1,
  517. ,ci,,1,
  518. n,,x,1,
  519. ai,,x,1,
  520. ei,,x,1,
  521. ou,,x,1,
  522. e,$,z,1,
  523. e,s$,,1,
  524. ,*,s,1,
  525. /
  526. /y,i,1
  527. /
  528. /z,z,1
  529. ,,z,1,
  530. ,,s,1,
  531. ,*,s,1,
  532. /
  533. /ã,ã,1
  534. /
  535. /õ,õ,1
  536. /
  537. /á,a,1
  538. /
  539. /é,é,1
  540. /
  541. /í,i,1
  542. /
  543. /ó,ó,1
  544. /
  545. /ú,u,1
  546. /
  547. /â,a,1
  548. ,¬,ã,1,t
  549. /
  550. /ê,e,1
  551. /
  552. /î,i,1
  553. /
  554. /ô,o,1
  555. /
  556. /û,u,1
  557. /
  558. /ç,s,1
  559. /
  560. /ü,u,1
  561. /
  562. ´
  563.  
  564.  
  565. Publicidade
  566.  
  567. DELPHI
  568. Postado em 27 mar 2005 às 00:00 ResponderCitar
  569. RESPOSTAS (4)
  570. 0
  571. Motta
  572. o uso é livre ?
  573.  
  574.  
  575. Postado em 28 mar 2005 às 00:00 ResponderCitar
  576. 0
  577. José Henrique
  578. É claro, Motta. Nem caberia eu pedir que os colegas avaliassem a rotina e dessem sugestões para depois restingir o uso, né? É livre!!! :D
  579.  
  580.  
  581. Postado em 28 mar 2005 às 00:00 ResponderCitar
  582. 0
  583. Motta
  584. Estas rotinas em geral convertem a string para um valor alfa-númerico montado com base na transcrição fonetica, o que permite uma busca aproximada mais acurada, pode-se até aproximar mais ou menos, se a rotina retornar um valor númerico.
  585.  
  586. veja a rotina do Oracle
  587.  
  588. SQLWKS> select ´MOTA´,SOUNDEX(´MOTA´) SDX
  589. 2> FROM DUAL
  590. 3>
  591. ´MOT SDX
  592. ---- ----
  593. MOTA M300
  594. 1 row selected.
  595. SQLWKS> select ´MOTTA´,SOUNDEX(´MOTTA´) SDX
  596. 2> FROM DUAL
  597. 3>
  598. ´MOTT SDX
  599. ----- ----
  600. MOTTA M300
  601. 1 row selected.
  602. SQLWKS> select ´MOITA´,SOUNDEX(´MOITA´) SDX
  603. 2> FROM DUAL
  604. 3>
  605. ´MOIT SDX
  606. ----- ----
  607. MOITA M300
  608.  
  609.  
  610. Testei para alguns casos e me pareceu legal
  611.  
  612.  
  613. Postado em 28 mar 2005 às 00:00 ResponderCitar
  614. 0
  615. Beppe
  616. É possível otimizar a função:
  617.  
  618. * V, V1, C, CN podem ser const´s
  619. * Ao invés de concatenações, pode usar uma TStringStream
  620. * Ao invés de Copy, compare caracter por caracter
  621.  
  622. Mas já foi bem astuto ao usar # como sentinelas. :) Eu usaria apenas ao final. Veja se não é possível testar o começo da string com n = 1, e buferizar o ultimo caractere examinado.
  623.  
  624. Quando tiver mais tempo dou uma olhada nas questões que você deixou em aberto.
  625.  
  626.  
  627.  
  628.  
  629.  
  630. -------------------------------------------------------------------------------------------------------------------------
  631. -------------------------------------------------------------------------------------------------------------------------
  632. -------------------------------------------------------------------------------------------------------------------------
  633. -------------------------------------------------------------------------------------------------------------------------
  634. -------------------------------------------------------------------------------------------------------------------------
  635. -------------------------------------------------------------------------------------------------------------------------
  636. -------------------------------------------------------------------------------------------------------------------------
  637.  
  638.  
  639.  
  640. 0. USO
  641. Depois de instalado:
  642.  
  643. PostgreSQL 9.x:
  644.     CREATE EXTENSION metaphoneptbr;
  645.     select metaphone_ptbr('qualquer');
  646. PostgreSQL 8.x:
  647.     psql -d banco -f /usr/share/postgresql/XX/contrib/metaphone_ptbr.sql
  648.         XX -> version of postgresql (8.3 or 8.4)
  649.     select metaphone_ptbr('qualquer');
  650. PHP:
  651.     <?php echo metaphoneptbr('qualquer'); ?>
  652.  
  653.  
  654. 1. INTRODUÇÃO
  655.  
  656. Metaphone for Brazilian Portuguese
  657.  
  658. O metafone é um algoritmo de transformação de texto baseado em regras
  659. fonéticas (http://en.wikipedia.com/wiki/Metaphone)
  660.  
  661. As regras foram baseadas em um trabalho conjunto publicado peal Prefeitura
  662. Municipal de Várzea Paulista (http://www2.varzeapaulista.sp.gov.br/metaphone),
  663. durante o projeto REDECA, voltado à infância e adolescência.
  664.  
  665. Este port é uma variação para o português, ao menos o brasileiro.
  666.  
  667. 2. O ALGORITMO
  668.  
  669. Assim como o Metaphone original e o Double Metaphone, o objetivo é criar uma
  670. palavra foneticamente representativa a partir da original utilizando as
  671. regras para o português brasileiro. Dessa forma, a busca é facilitada por
  672. transformar cerca de 10 a 50 palavras em uma única representação. O custo de
  673. uma pesquisa em um banco de dados tradicional para as variantes cai
  674. drasticamente, de forma que um segundo algoritmo de proximidade (levenshtein,
  675. similar text) para um ordenamento eficaz se torna viável pela menor
  676. quantidade de registros a serem analisados.
  677.  
  678. Basicamente, transforma uma palavra em uma forma fonética, a fim de que
  679. palavras foneticamente semelhantes possam ser encontradas, resolvendo a maior
  680. parte dos casos de busca de nomes de pessoas, ruas, além de permitir busca por
  681. palavras foneticamente semelhantes em um dicionário.
  682.  
  683. Pode-se dizer que o algoritmo simplifica a quantidade de símbolos das palavras,
  684. mantendo apenas o essencial para identificar seu núcleo. No caso do português
  685. (e de várias outras línguas também), as consoantes são as letras que carregam a
  686. identificação de uma palavra. Logo, considera-se trocar a palavra por símbolos
  687. que representam aquela sonoridade.
  688.  
  689. O algoritmo não é complexo computacionalmente. Seu valor está no estudo das
  690. regras fonéticas e o contexto das letras para determinação do som mais
  691. apropriado, algumas vezes analisando até duas letras à frente ou para trás. A
  692. sua implementação foi construída visando simplicidade e agilidade.
  693.  
  694. Para simplificar a representação do algoritmo, tomemos as seguintes notações:
  695.  
  696. SIMBOLO - NOTACAO
  697. ------------------------------------------
  698. ^       - Representa o começo da palavra
  699. $       - Representa o fim da palavra
  700. []      - igual em regex: qualquer um dentro dos colchetes
  701. v       - (minúsculo) representa uma vogal qualquer
  702. c       - (minúsculo) representa uma consoante qualquer
  703. .   - Qualquer letra
  704. 0   - (nulo) Representa que o símbolo foi ignorado e não mapeado.
  705. letras em maiúsculo - representam uma vogal ou consoante real em particular
  706.  
  707.  
  708. LETRAS  -> REPRESENTAÇÃO FONÉTICA (COMENTARIOS)
  709. ------------------------------------------
  710. ^-> v (ou seja, copia a vogal)
  711. B       -> B
  712. C[AOU]  -> K
  713. Cc      -> K
  714. C[EI]   -> S
  715. CHR -> K
  716. CH  -> X (regra mais genérica aplica-se por último)
  717. C$  -> K
  718. Ç  -> S
  719. D       -> D
  720. F   -> F
  721. G[AOU]  -> G
  722. G[EI]   -> J
  723. GH[EI]  -> J
  724. GHc -> G
  725. ^Hv -> v
  726. H   -> 0 (Outros casos de aparição de H devem ser ignorados)
  727. J   -> J
  728. K   -> K
  729. LH  -> 1 (não tem representacao no metaphone original)
  730. Lv  -> L
  731. M   -> M
  732. N$  -> M
  733. NH  -> 3 (não tem representação no metaphone original)
  734. P   -> P
  735. PH  -> F
  736. Q   -> K
  737. ^-> 2 (não tem representação no metaphone original)
  738. R$  -> 2 (não tem representação no metaphone original)
  739. RR  -> 2
  740. vRv -> R
  741. .Rc -> R
  742. cRv -> R
  743. SS  -> S
  744. SH  -> X
  745. SC[EI]  -> S
  746. SC[AUO] -> SK (sim - duas letras porque tem sons distintos quando acompanhadas de U ou O).
  747. SCH -> X
  748. Sc  -> S
  749. S   -> S (caso as outras regras não se apliquem, esta entra em vigor)
  750. T   -> T
  751. TH  -> T
  752. V   -> V
  753. Wv  -> V
  754. Wc  -> 0
  755. X$  -> X (o mais adequado seria KS, mas há de se considerar alguns nomes separados por espaços, tornando assim X uma representação mais interessante, embora não perfeitamente acurada)
  756. ^EXv    -> Z
  757. .EX[EI] -> X
  758. .EX[AOU]-> X
  759. EX[EI]  -> X
  760. EX[AOU] -> KS
  761. EX[PTC] -> S
  762. EX. -> KS
  763. [vCKGLRX][AIOU]X    -> X
  764. [DFMNPQSTVZ][AIOU]X -> KS
  765. X   -> X (caso nenhuma caso acima case com a palavra, aplica-se esta regra)
  766. Y   -> I (é tratado como vogal para todos os efeitos)
  767. Z$  -> S
  768. Z   -> Z
  769.  
  770.  
  771.  
  772.  
  773. A escolha em uma implementação à parte do código original se dá por duas razões principais:
  774. 1. O Metaphone original usa regras fonéticas americanas. O estrangeirismo na língua inglesa
  775.    é resolvido com uma segunda string fornecida pelo Double Metaphone para resolver alguns
  776.    empecilhos da primeira  versão. De  qualquer forma, o metaphone original não funciona de
  777.    forma satisfatória para o português.
  778.  
  779. 2. Implementar uma terceira string variante a partir do código metaphone seria uma tarefa
  780.    hercúlea e provavelmente seriam inseridos erros no código original, pela dificuldade em
  781.    expandí-lo de forma apropriada. O código contém adaptações (em especial o Double Metaphone)
  782.    que buscam abranger todas as palavras do mundo em uma representação fonética única.
  783.    Contudo a maneira utilizada para tal é inviável, porque as letras e os sons são contextuais
  784.    à língua utilizada.
  785.  
  786. O algoritmo mantém  algumas convenções usadas no metaphone original e acrescenta outras, para sons
  787. que não existem ou são considerados no inglês (o LH, NH).
  788.  
  789. A maior dificuldade do algoritmo atual é trabalhar com nomes estrangeiros, que praticamente fogem
  790. das regras comuns de pronunciação, exigindo um trato quase à parte para alguns nomes, como  Harry.
  791. Felizmente, esses tipos de nomes não são muito comuns, mas há outras formas de estrangeirismo mais
  792. complicadas de se tratar e que sempre vão precisar de um cuidado mais apurado ou uma convenção simbólica,
  793. a fim de representá-los, mesmo que não 'soem' como o esperado na representação fonética, mas que possam
  794. ser enquadrados ao lado de nomes semelhantes em grafia para a busca se tornar efetiva.
  795.  
  796.  
  797.  * * *
  798.  
  799. 3. O FUTURO
  800.  
  801. Dado as principais dificuldades fonéticas práticas, encontramos três frentes de trabalho:
  802.     a) Conversão fonética fiel à norma. Aqui as regras gramaticais são aplicadas e não
  803.     são tratadas as exceções (como acontece com os nomes), exceto aquelas previstas
  804.     pela língua.
  805.  
  806.     b) Conversão fonética semi-fiel. Acrescenta algumas exceções práticas do cotidiano,
  807.     buscando alcançar um equilíbrio entre a grafia e a fonética dos nomes que fogem à regra.
  808.     Essa é a implementação atual.
  809.  
  810.     c) Conversão fonética coloquial. Visando nomes e exceções às regras, inclui todas as regras
  811.     fonéticas comuns, mas as exceções tem mais força que as regras. A possível consequência a
  812.     este uso é a simplificação da identidade fonética da palavra, a fim de capturar maior número
  813.     de semelhantes. Difícil de definir as regras por serem subjetivas.
  814.  
  815. As conseqüências para essas frentes são a produção de diferentes metafones para as palavras, em grau
  816. de fidelidade. Ou seja, para o primeiro caso, a chave fonética seria a mais completa e também a mais
  817. restritiva, pois diminuiria o número de casos semelhantes. Para o último, seria a mais simples, mantendo
  818. apenas a sonoridade mais marcante da palavra e teria um número de casos semelhantes muito mais alto.
  819.  
  820.  
  821.  * * *
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement