strings statement online ejemplo c# string comparison phonetics

statement - string.compare c#



¿Cómo puedo medir la similitud entre 2 cuerdas? (12)

Dadas dos cadenas de text2 y text2

public SOMEUSABLERETURNTYPE Compare(string text1, string text2) { // DO SOMETHING HERE TO COMPARE }

Ejemplos:

  1. Primera cadena: StackOverflow

    Segunda Cadena: StaqOverflow

    Retorno: la similitud es 91%

    El retorno puede ser en% o algo así.

  2. Primera cadena: la prueba de texto simple

    Segunda cadena: la prueba de texto complejo

    Retorno: Los valores pueden considerarse iguales.

¿Algunas ideas? ¿Cuál es la mejor manera de hacer esto?


Metaphone 3 es la tercera generación del algoritmo Metaphone. Aumenta la precisión de la codificación fonética desde el 89% de Double Metaphone hasta el 98% , comparada con una base de datos de las palabras en inglés más comunes y con nombres y palabras que no son en inglés que son familiares en América del Norte. Esto produce una codificación fonética extremadamente confiable para las pronunciaciones americanas.

Metaphone 3 fue diseñado y desarrollado por Lawrence Philips, quien diseñó y desarrolló los algoritmos originales Metaphone y Double Metaphone.


Aquí hay un código que he escrito para un proyecto en el que estoy trabajando. Necesito saber la relación de similitud de las cadenas y la relación de similitud basada en las palabras de las cadenas. Este último, quiero saber tanto la Relación de similitud de palabras de la cadena más pequeña (de modo que si todas las palabras existen y coinciden en la cadena más grande, el resultado será del 100%) y la Relación de similitud de palabras de la cadena más grande (a la que llamo RealWordsRatio ). Uso el algoritmo de Levenshtein para encontrar la distancia. El código no está optimizado, hasta ahora, pero funciona como se esperaba. Espero que les sea útil.

public static int Compute(string s, string t) { int n = s.Length; int m = t.Length; int[,] d = new int[n + 1, m + 1]; // Step 1 if (n == 0) { return m; } if (m == 0) { return n; } // Step 2 for (int i = 0; i <= n; d[i, 0] = i++) { } for (int j = 0; j <= m; d[0, j] = j++) { } // Step 3 for (int i = 1; i <= n; i++) { //Step 4 for (int j = 1; j <= m; j++) { // Step 5 int cost = (t[j - 1] == s[i - 1]) ? 0 : 1; // Step 6 d[i, j] = Math.Min( Math.Min(d[i - 1, j] + 1, d[i, j - 1] + 1), d[i - 1, j - 1] + cost); } } // Step 7 return d[n, m]; } double GetSimilarityRatio(String FullString1, String FullString2, out double WordsRatio, out double RealWordsRatio) { double theResult = 0; String[] Splitted1 = FullString1.Split(new char[]{'' ''}, StringSplitOptions.RemoveEmptyEntries); String[] Splitted2 = FullString2.Split(new char[]{'' ''}, StringSplitOptions.RemoveEmptyEntries); if (Splitted1.Length < Splitted2.Length) { String[] Temp = Splitted2; Splitted2 = Splitted1; Splitted1 = Temp; } int[,] theScores = new int[Splitted1.Length, Splitted2.Length];//Keep the best scores for each word.0 is the best, 1000 is the starting. int[] BestWord = new int[Splitted1.Length];//Index to the best word of Splitted2 for the Splitted1. for (int loop = 0; loop < Splitted1.Length; loop++) { for (int loop1 = 0; loop1 < Splitted2.Length; loop1++) theScores[loop, loop1] = 1000; BestWord[loop] = -1; } int WordsMatched = 0; for (int loop = 0; loop < Splitted1.Length; loop++) { String String1 = Splitted1[loop]; for (int loop1 = 0; loop1 < Splitted2.Length; loop1++) { String String2 = Splitted2[loop1]; int LevenshteinDistance = Compute(String1, String2); theScores[loop, loop1] = LevenshteinDistance; if (BestWord[loop] == -1 || theScores[loop, BestWord[loop]] > LevenshteinDistance) BestWord[loop] = loop1; } } for (int loop = 0; loop < Splitted1.Length; loop++) { if (theScores[loop, BestWord[loop]] == 1000) continue; for (int loop1 = loop + 1; loop1 < Splitted1.Length; loop1++) { if (theScores[loop1, BestWord[loop1]] == 1000) continue;//the worst score available, so there are no more words left if (BestWord[loop] == BestWord[loop1])//2 words have the same best word { //The first in order has the advantage of keeping the word in equality if (theScores[loop, BestWord[loop]] <= theScores[loop1, BestWord[loop1]]) { theScores[loop1, BestWord[loop1]] = 1000; int CurrentBest = -1; int CurrentScore = 1000; for (int loop2 = 0; loop2 < Splitted2.Length; loop2++) { //Find next bestword if (CurrentBest == -1 || CurrentScore > theScores[loop1, loop2]) { CurrentBest = loop2; CurrentScore = theScores[loop1, loop2]; } } BestWord[loop1] = CurrentBest; } else//the latter has a better score { theScores[loop, BestWord[loop]] = 1000; int CurrentBest = -1; int CurrentScore = 1000; for (int loop2 = 0; loop2 < Splitted2.Length; loop2++) { //Find next bestword if (CurrentBest == -1 || CurrentScore > theScores[loop, loop2]) { CurrentBest = loop2; CurrentScore = theScores[loop, loop2]; } } BestWord[loop] = CurrentBest; } loop = -1; break;//recalculate all } } } for (int loop = 0; loop < Splitted1.Length; loop++) { if (theScores[loop, BestWord[loop]] == 1000) theResult += Splitted1[loop].Length;//All words without a score for best word are max failures else { theResult += theScores[loop, BestWord[loop]]; if (theScores[loop, BestWord[loop]] == 0) WordsMatched++; } } int theLength = (FullString1.Replace(" ", "").Length > FullString2.Replace(" ", "").Length) ? FullString1.Replace(" ", "").Length : FullString2.Replace(" ", "").Length; if(theResult > theLength) theResult = theLength; theResult = (1 - (theResult / theLength)) * 100; WordsRatio = ((double)WordsMatched / (double)Splitted2.Length) * 100; RealWordsRatio = ((double)WordsMatched / (double)Splitted1.Length) * 100; return theResult; }


El módulo Perl Text::Phonetic tiene implementaciones de varios algoritmos.



Hay varias formas diferentes de hacer esto. Eche un vistazo a la página de Wikipedia "Medidas de similitud de cadenas" para obtener enlaces a otras páginas con algoritmos.

Sin embargo, no creo que ninguno de esos algoritmos tome en consideración los sonidos, por lo que "overq overq" sería tan similar a "overflow" como "overw overw" a pesar de que el primero es más similar en términos de pronunciación.

Acabo de encontrar otra página que ofrece más opciones ... en particular, el algoritmo Soundex ( Wikipedia ) puede estar más cerca de lo que está buscando.


Para lidiar con los "sonidos parecidos" es posible que desee investigar la codificación utilizando un algoritmo fonético como Double Metaphone o soundex. No sé si el cálculo de las distancias de Levenshtein en cadenas codificadas fonéticas sería beneficioso o no, pero podría ser una posibilidad. Alternativamente, puede usar una heurística como: convierta cada palabra de la cadena a su forma codificada y elimine cualquier palabra que aparezca en ambas cadenas y reemplácelas con una sola representación antes de calcular la distancia de Levenshtein.




Si está comparando valores en una base de datos SQL, puede usar la función SOUNDEX . Si consulta a Google para SOUNDEX y C #, algunas personas han escrito una función similar para eso y VB.