Olá pessoal, Guionardo, você não é brincadeira não, matou a dúvida e mostrou a função, rsrsrsrsrsrsrs. Desse jeito os 2 demos que coloquei na 4shared vão virar sarcófagos, rsrsrsrsrsrsrs. Você é fera, isso não é um elogio, é a realidade. Funções úteis para strings (as que iniciam com 'sc' foram escritas por mim): ----------------------------------------------------------------------- function scRemoveAllChars(Ch: Char; S: string): string; var I: Integer; begin I := Length(S); while (Length(S) > 0) and (I > 0) do begin if S[I] = Ch then Delete(S, I, 1); Dec(I); end; Result := S; end; ----------------------------------------------------------------------- function scRemoveCharactersOfString(Chrs: array of Char; Str: string): string; var I: Integer; S: string; begin S := Str; for I := 0 to High(Chrs) do S := scRemoveAllChars(Chrs[I], S); Result := S; end; ----------------------------------------------------------------------- function RemovesAccent1(S: string): string; const WithAccent = 'àâêôûãõáéíóúçüÀÂÊÔÛÃÕÁÉÍÓÚÇÜ'; Stressless = 'aaeouaoaeioucuAAEOUAOAEIOUCU'; var I: Integer; begin for I := 1 to Length(S) do if Pos(S[I], WithAccent) <> 0 then S[I] := Stressless[Pos(S[I], WithAccent)]; Result := S; end; ----------------------------------------------------------------------- function RemovesAccents2(S: string ): string; var I: Integer; begin for I := 1 to Length(S) do case S[I] of 'á': S[I] := 'a'; 'é': S[I] := 'e'; 'í': S[I] := 'i'; 'ó': S[I] := 'o'; 'ú': S[I] := 'u'; 'à': S[I] := 'a'; 'è': S[I] := 'e'; 'ì': S[I] := 'i'; 'ò': S[I] := 'o'; 'ù': S[I] := 'u'; 'â': S[I] := 'a'; 'ê': S[I] := 'e'; 'î': S[I] := 'i'; 'ô': S[I] := 'o'; 'û': S[I] := 'u'; 'ä': S[I] := 'a'; 'ë': S[I] := 'e'; 'ï': S[I] := 'i'; 'ö': S[I] := 'o'; 'ü': S[I] := 'u'; 'ã': S[I] := 'a'; 'õ': S[I] := 'o'; 'ñ': S[I] := 'n'; 'ç': S[I] := 'c'; 'Á': S[I] := 'A'; 'É': S[I] := 'E'; 'Í': S[I] := 'I'; 'Ó': S[I] := 'O'; 'Ú': S[I] := 'U'; 'À': S[I] := 'A'; 'È': S[I] := 'E'; 'Ì': S[I] := 'I'; 'Ò': S[I] := 'O'; 'Ù': S[I] := 'U'; 'Â': S[I] := 'A'; 'Ê': S[I] := 'E'; 'Î': S[I] := 'I'; 'Ô': S[I] := 'O'; 'Û': S[I] := 'U'; 'Ä': S[I] := 'A'; 'Ë': S[I] := 'E'; 'Ï': S[I] := 'I'; 'Ö': S[I] := 'O'; 'Ü': S[I] := 'U'; 'Ã': S[I] := 'A'; 'Õ': S[I] := 'O'; 'Ñ': S[I] := 'N'; 'Ç': S[I] := 'C'; end; Result := S; end; Um abraço! Silvio Clécio Contatos/Blog Skype: silvioprog Yahoo! Messenger: [EMAIL PROTECTED] MSN (Hotmail): [EMAIL PROTECTED] BlogSpot: http://silvioclecio.blogspot.com/
----- Mensagem original ---- De: Guionardo Furlan <[EMAIL PROTECTED]> Para: delphi-br@yahoogrupos.com.br Enviadas: Quarta-feira, 8 de Outubro de 2008 17:34:22 Assunto: Re: [delphi-br] Similaridade entre duas Strings Elogio de vez em quando vai bem, eheh. Bom, tá aí o código, testado por aqui e funcionando. No meu cálculo manual deu diferença ao comparar os nomes JOÃO e JONAS porque não considerei a diferença de tamanho das strings. Não é um componente, é uma função. -------- unit GStrings; interface /// Obtém a similaridade entre duas strings retornando um valor entre 0 e 1 function Similaridade( Origem, Destino: string): Single; implementation uses SysUtils, GuioUtils; function Similaridade( Origem, Destino: string): Single; var i: Integer; SimCar: Integer; // Similaridade de caracteres SimOrd: Integer; // Similaridade de ordem Lista: array of string; function Validacao: Boolean; begin Result := (Length(Origem) > 0) and (Length(Destino) > 0); end; procedure SimilaridadeCaracte r; var j: Integer; begin SimCar := 0; for j := 1 to Length(Origem) do if Pos(Origem[j] , Destino) > 0 then Inc(SimCar); end; procedure RemoveNaoCoincident es(var s1, s2: string); begin i := 1; while i <= Length(s1) do if Pos(s1[i], s2) = 0 then Delete(s1, i, 1) else Inc(i); end; procedure GeraLista; var npalavras: Integer; // Número de "palavras" j, k: Integer; begin npalavras := (Sqr(Length( Origem)) + Length(Origem) ) div 2; SetLength(Lista, npalavras); i := 0; for j := 1 to Length(Origem) do // j recebe o tamanho de cada palavra for k := 1 to Length(Origem) - j + 1 do // k recebe a posicao de cada palavra begin Lista[i] := Copy(Origem, k, j); Inc(i); end; end; procedure SimilaridadeOrdem; var j: Integer; begin SimOrd := 0; for j := 0 to Length(Lista) - 1 do if Pos(Lista[j] , Destino) > 0 then Inc(SimOrd); Result := Result * (SimOrd / Length(Lista) ); SetLength(Lista, 0); end; begin // 1. Transformar os textos para a mesma caixa e remover espaços em branco Origem := AnsiUpperCase( Trim(RemoveAcent os(Origem) )); Destino := AnsiUpperCase( Trim(RemoveAcent os(Destino) )); // 2a. Verificar se os textos são vazios: se forem, similaridade 0 e sai if not Validacao then begin Result := 0; Exit; end; // 2b. Verificar se os textos são iguais: se forem, similaridade 100% // e termina o processo if SameText(Origem, Destino) then begin Result := 1; Exit; end; // 3. para cada caracter do texto origem verificar se ele existe no texto // destino, e em caso positivo, incrementar 1 no contador de similaridade. SimilaridadeCaracte r; // 4. o quociente contador / número de caracteres no destino indica a // similaridade sem considerar a ordem dos caracteres. Result := SimCar / Length(Destino) ; if Result = 0 then Exit; // 5. considerando a ordem, remove-se os caracteres da origem que não // existem no destino e os caracteres do destino que não existem na // origem, igualando os dois textos RemoveNaoCoincident es(Origem, Destino); RemoveNaoCoincident es(Destino, Origem); // 6. agora, com uma função que gere uma lista de "palavras" formadas // pelos caracteres da origem, da seguinte forma: // origem ajustada: "peto", com os caracteres não coincidentes removidos, // a lista gerada seria a seguinte // p, e, t, o, pe, et, to, pet, eto, peto: 4 caracteres = 10 palavras // map = m, a, p, ma, ap, map: 3 caracteres = 6 palavras // jorge = j, o, r, g, e, jo, or, rg, ge, jor, org, rge, jorg, orge, // jorge: 5 caracteres = 15 palavras // O número de "palavras" dentro da lista é definido pela fórmula // 0,5j^2+0,5j, onde j é o número de caracteres do texto origem ajustado. GeraLista; // Cada palavra da lista encontrada dentro da palavra destino ajustada // incrementa uma unidade no contador de similaridade de ordem. // A similaridade de ordem é o quociente do contador sobre o número de // palavras da lista. SimilaridadeOrdem; end; end. --------- PS: Duas referências no código (guioutils e RemoveAcentos) não estão disponíveis. É que minha função de remoção de acentos usa uma tecnologia avançadíssima com algoritmos genéticos e inteligência artificial, portanto não disponibilizarei de grátis aqui. :-) 2008/10/8 Roberto <[EMAIL PROTECTED] br>: > Guionardo, tu tá de sacanagem, né.. > > Quando descansar bem, completa a explanação com um componente aqui prá nois, > > Matou a cobra, agora mostra o componente (se ainda houver fosfato). > > Parabéns e entenda a brincadeira como elogio > > Abraço > Roberto (RJ) > > ----- Original Message ----- > From: Guionardo Furlan > To: [EMAIL PROTECTED] os.com.br > Sent: Tuesday, October 07, 2008 10:13 PM > Subject: Re: [delphi-br] Similaridade entre duas Strings > > um bom exercício, vou dar meu palpite: > > 1. transformar os textos para a mesma caixa (alta ou baixa) > 2. Verificar se os textos são iguais: se forem, similaridade 100% e > termina o processo. > 3. para cada caracter do texto origem verificar se ele existe no texto > destino, e em caso positivo, incrementar 1 no contador de > similaridade. > 4. o quociente contador / número de caracteres no destino indica a > similaridade sem considerar a ordem dos caracteres. > > Por exemplo, "pedto" e "pedro" são similares 4 caracteres em 5, > indicando 80% de similaridade sem verificação de ordem. > > 5. considerando a ordem, remove-se os caracteres da origem que não > existem no destino e os caracteres do destino que não existem na > origem, igualando os dois textos > 6. agora, com uma função que gere uma lista de "palavras" formadas > pelos caracteres da origem, da seguinte forma: > origem ajustada: "peto", com os caracteres não coincidentes removidos, > a lista gerada seria a seguinte > p, e, t, o, pe, et, to, pet, eto, peto: 4 caracteres = 10 palavras > map = m, a, p, ma, ap, map: 3 caracteres = 6 palavras > jorge = j, o, r, g, e, jo, or, rg, ge, jor, org, rge, jorg, orge, > jorge: 5 caracteres = 15 palavras > O número de "palavras" dentro da lista é definido pela fórmula > 0,5j^2+0,5j, onde j é o número de caracteres do texto origem ajustado. > Cada palavra da lista encontrada dentro da palavra destino ajustada > incrementa uma unidade no contador de similaridade de ordem. > A similaridade de ordem é o quociente do contador sobre o número de > palavras da lista. > No exemplo acima, temos a mesma ordem dos caracteres e portanto, 100% > de similaridade por ordem. > > Multiplicando os dois quocientes, teríamos um fator de similaridade > entre as palavras, neste caso, 80% x 100% = 80% > > com outro exemplo, poderíamos ter: > JOAO e JONAS > > As letras J, O, A e O existem todas dentro de JONAS, portanto temos > 100% até aqui > Fazendo a intersecção, temos os dois textos ajustados: > JOAO e JOA > > com a lista de palavras temos > J (1), O (1), A (1), O (1), JO (1), OA (1), AO (0), JOA (1), OAO (0), > JOAO (0), somando 7 coincidências em 10 possibilidades, resultando em > 70%. > > Multiplicando os dois quocientes, temos 70% de similaridade. > > Agora é só codificar pra OP e ver se a coisa serve. > > PS: fiz isso depois da janta, e meio cansado. Provavelmente deve haver > um algoritmo mais elaborado, usando redes neurais, ou até mesmo uma > função do delphi que resolve a parada. Mas é legal pra gente queimar > um pouco de fosfato fora dos problemas comuns. > > 2008/10/7 Osmar Souza <osmar_listas@ yahoo.com. br>: >> Olá Pessoal, >> >> Alguem já precisou comparar a similaridade entre duas strings e >> supor a porcetagem de similaridade entre elas? >> >> Exemplo: >> >> Em uma caixa de texto a pessoa digitou "pedto". O sistema analisou >> e pergunta se o que ele esta procurando não é "pedro". Como no Google. >> >> Estou precisando de um algoritimo desses para tentar diminuir o >> número de erros no cadastro. Como os requisitos do sistema diz que o >> nome é o mais importante e que o resto não é necessário, vemos uma >> mesma pessoa jurídica, por exemplo, cadastradas de 10 formas diferentes. -- Timeo hominem unius libri Cogito ergo sum - Carpe diem []s Guionardo Furlan http://guionardo. blogspot. com . Novos endereços, o Yahoo! que você conhece. Crie um email novo com a sua cara @ymail.com ou @rocketmail.com. http://br.new.mail.yahoo.com/addresses [As partes desta mensagem que não continham texto foram removidas]