Η συνηθισμένη απάντηση σε τέτοιους προβληματισμούς, είναι ένας similarity ranking αλγόριθμος, που εξετάζει 2 λέξεις/φράσεις, και σου δίνει ένα double αποτέλεσμα με κάποιο ποσοστό ομοιότητας ανάμεσα στα 2 strings. Οπότε π.χ. αν το λάθος σου είναι 'ίνα' και δεν υπάρχει κάτι άλλο στο string σου, τα 'Μίνα', 'Λίνα' κτλ κτλ ... μάλλον θα δώσουν την ίδια απάντηση. Και λογικό δεν είναι;
Κοίταγα χτές το βράδυ πως θα μπορούσε να γίνει κάτι τέτοιο σχετικά εύκολα στη βάση, και δεν βρήκα τίποτα σχετικό στα 10 λεπτά που έδωσα ... αλλά ...
Αν η βάση σου είναι SQL Server, τότε μπορείς να γράψεις σε .NET γλώσσες δικά σου "extentions" στον SQL.
Έτσι, και μιας και το δεύτερο link στο Google για "similarity ranking algorithm C#" μου επέστρεψε
μια υλοποίηση σε ... Java ... κάθησα λίγο στο VS και την έκανα C# για SQL Server - ένα user function που μπορείς να χρησιμοποιήσεις μέσα στην SQL σου, κάπως έτσι:
SELECT [dbo].[SimilarityRank] ( 'aggeloa karantzalia' ,'aggelos karantzalis')
... αυτό μου γυρίζει 0.875, το οποίο μου φαίνεται λογικό νούμερο με 2 γράμματα λάθος στα 19-20.
Τέλος πάντων όμως, αυτό δεν είναι το κύριο πρόβλημά σου. Το κύριο πρόβλημα σου είναι ότι χρειάζεσαι ένα "Dictionary" με τα πιθανά permutations, και πώς περιορίζεις το μέγεθός του ...
Επειδή έχω μόνο VS 2008 σπίτι, κάνω απλώς copy paste τον κώδικα, sorry about that, και το κάνω attach σαν .txt (
γιατί ρε παιδιά δεν μπορούμε να ανεβάσουμε .cs ;;; )
using System;
using
System.Data;
using
System.Data.SqlClient;
using
System.Data.SqlTypes;
using
Microsoft.SqlServer.Server;
using
System.Collections;
using
System.Collections.Generic;
public partial class UserDefinedFunctions
{
/// <summary>
/// Calculates a similarity
ranking value for the two specified strings
/// </summary>
/// <returns></returns>
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlDouble SimilarityRank(string
strValue1, string strValue2)
{
IList<string>
pairs1 = WordLetterPairs(strValue1);
IList<string>
pairs2 = WordLetterPairs(strValue2);
int intersection = 0;
int union = pairs1.Count + pairs2.Count;
foreach(string pair1 in pairs1){
for (int j = 0; j
< pairs2.Count; j++)
{
string pair2 = pairs2[j];
if (pair1.Equals(pair2))
{
intersection++;
pairs2.RemoveAt(j);
break;
}
}
}
return new SqlDouble((2.0 * intersection) / union);
}
/// <summary>
/// Splits the input into
"words" and collects all character pairs
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
private static IList<string>
WordLetterPairs(string str)
{
List<string>
allPairs = new List<string>();
// Tokenize the string and put the tokens/words into an
array
string[] words = str.Split('
', '\n', '\t');
// For each word
foreach (string word in words)
foreach (string
pairInWord in LetterPairs(word))
allPairs.Add(pairInWord);
return allPairs;
}
/// <summary>
/// Retrieves all the
character pairs in the given string
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
private static string[] LetterPairs(string
str)
{
int numPairs = str.Length - 1;
string[] pairs = new string[numPairs];
for (int i = 0; i
< numPairs; i++)
{
pairs
=
str.Substring(i, 2);
}
return
pairs;
}
};
Angel
O:]