mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-08-10 16:14:40 +02:00
* Moved levenshtein method to TomahawkUtils.
This commit is contained in:
@@ -498,13 +498,13 @@ Query::howSimilar( const Tomahawk::result_ptr& r )
|
||||
{
|
||||
// result values
|
||||
const QString rArtistname = r->artist()->sortname();
|
||||
const QString rAlbumname = DatabaseImpl::sortname( r->album()->name() );
|
||||
const QString rAlbumname = r->album()->sortname();
|
||||
const QString rTrackname = DatabaseImpl::sortname( r->track() );
|
||||
|
||||
// normal edit distance
|
||||
int artdist = levenshtein( m_artistSortname, rArtistname );
|
||||
int albdist = levenshtein( m_albumSortname, rAlbumname );
|
||||
int trkdist = levenshtein( m_trackSortname, rTrackname );
|
||||
int artdist = TomahawkUtils::levenshtein( m_artistSortname, rArtistname );
|
||||
int albdist = TomahawkUtils::levenshtein( m_albumSortname, rAlbumname );
|
||||
int trkdist = TomahawkUtils::levenshtein( m_trackSortname, rTrackname );
|
||||
|
||||
// max length of name
|
||||
int mlart = qMax( m_artistSortname.length(), rArtistname.length() );
|
||||
@@ -521,7 +521,7 @@ Query::howSimilar( const Tomahawk::result_ptr& r )
|
||||
const QString artistTrackname = DatabaseImpl::sortname( fullTextQuery() );
|
||||
const QString rArtistTrackname = DatabaseImpl::sortname( r->artist()->name() + " " + r->track() );
|
||||
|
||||
int atrdist = levenshtein( artistTrackname, rArtistTrackname );
|
||||
int atrdist = TomahawkUtils::levenshtein( artistTrackname, rArtistTrackname );
|
||||
int mlatr = qMax( artistTrackname.length(), rArtistTrackname.length() );
|
||||
float dcatr = (float)( mlatr - atrdist ) / mlatr;
|
||||
|
||||
@@ -922,83 +922,3 @@ Query::infoSystemFinished( QString target )
|
||||
|
||||
emit updated();
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Query::levenshtein( const QString& source, const QString& target )
|
||||
{
|
||||
// Step 1
|
||||
const int n = source.length();
|
||||
const int m = target.length();
|
||||
|
||||
if ( n == 0 )
|
||||
return m;
|
||||
if ( m == 0 )
|
||||
return n;
|
||||
|
||||
// Good form to declare a TYPEDEF
|
||||
typedef QVector< QVector<int> > Tmatrix;
|
||||
Tmatrix matrix;
|
||||
matrix.resize( n + 1 );
|
||||
|
||||
// Size the vectors in the 2.nd dimension. Unfortunately C++ doesn't
|
||||
// allow for allocation on declaration of 2.nd dimension of vec of vec
|
||||
for ( int i = 0; i <= n; i++ )
|
||||
{
|
||||
QVector<int> tmp;
|
||||
tmp.resize( m + 1 );
|
||||
matrix.insert( i, tmp );
|
||||
}
|
||||
|
||||
// Step 2
|
||||
for ( int i = 0; i <= n; i++ )
|
||||
matrix[i][0] = i;
|
||||
for ( int j = 0; j <= m; j++ )
|
||||
matrix[0][j] = j;
|
||||
|
||||
// Step 3
|
||||
for ( int i = 1; i <= n; i++ )
|
||||
{
|
||||
const QChar s_i = source[i - 1];
|
||||
|
||||
// Step 4
|
||||
for ( int j = 1; j <= m; j++ )
|
||||
{
|
||||
const QChar t_j = target[j - 1];
|
||||
|
||||
// Step 5
|
||||
int cost;
|
||||
if ( s_i == t_j )
|
||||
cost = 0;
|
||||
else
|
||||
cost = 1;
|
||||
|
||||
// Step 6
|
||||
const int above = matrix[i - 1][j];
|
||||
const int left = matrix[i][j - 1];
|
||||
const int diag = matrix[i - 1][j - 1];
|
||||
|
||||
int cell = ( ( ( left + 1 ) > ( diag + cost ) ) ? diag + cost : left + 1 );
|
||||
if ( above + 1 < cell )
|
||||
cell = above + 1;
|
||||
|
||||
// Step 6A: Cover transposition, in addition to deletion,
|
||||
// insertion and substitution. This step is taken from:
|
||||
// Berghel, Hal ; Roach, David : "An Extension of Ukkonen's
|
||||
// Enhanced Dynamic Programming ASM Algorithm"
|
||||
// (http://www.acm.org/~hlb/publications/asm/asm.html)
|
||||
if ( i > 2 && j > 2 )
|
||||
{
|
||||
int trans = matrix[i - 2][j - 2] + 1;
|
||||
|
||||
if ( source[ i - 2 ] != t_j ) trans++;
|
||||
if ( s_i != target[ j - 2 ] ) trans++;
|
||||
if ( cell > trans ) cell = trans;
|
||||
}
|
||||
matrix[i][j] = cell;
|
||||
}
|
||||
}
|
||||
|
||||
// Step 7
|
||||
return matrix[n][m];
|
||||
}
|
||||
|
@@ -97,7 +97,7 @@ public:
|
||||
QID id() const;
|
||||
|
||||
/// sorter for list of results
|
||||
static bool resultSorter( const result_ptr &left, const result_ptr& right );
|
||||
static bool resultSorter( const result_ptr& left, const result_ptr& right );
|
||||
|
||||
/// true when a perfect result has been found (score of 1.0)
|
||||
bool solved() const { return m_solved; }
|
||||
@@ -221,7 +221,6 @@ private:
|
||||
void checkResults();
|
||||
|
||||
void updateSortNames();
|
||||
static int levenshtein( const QString& source, const QString& target );
|
||||
|
||||
void parseSocialActions();
|
||||
|
||||
|
@@ -329,13 +329,93 @@ void
|
||||
msleep( unsigned int ms )
|
||||
{
|
||||
#ifdef WIN32
|
||||
Sleep( ms );
|
||||
Sleep( ms );
|
||||
#else
|
||||
::usleep( ms * 1000 );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
levenshtein( const QString& source, const QString& target )
|
||||
{
|
||||
// Step 1
|
||||
const int n = source.length();
|
||||
const int m = target.length();
|
||||
|
||||
if ( n == 0 )
|
||||
return m;
|
||||
if ( m == 0 )
|
||||
return n;
|
||||
|
||||
// Good form to declare a TYPEDEF
|
||||
typedef QVector< QVector<int> > Tmatrix;
|
||||
Tmatrix matrix;
|
||||
matrix.resize( n + 1 );
|
||||
|
||||
// Size the vectors in the 2.nd dimension. Unfortunately C++ doesn't
|
||||
// allow for allocation on declaration of 2.nd dimension of vec of vec
|
||||
for ( int i = 0; i <= n; i++ )
|
||||
{
|
||||
QVector<int> tmp;
|
||||
tmp.resize( m + 1 );
|
||||
matrix.insert( i, tmp );
|
||||
}
|
||||
|
||||
// Step 2
|
||||
for ( int i = 0; i <= n; i++ )
|
||||
matrix[i][0] = i;
|
||||
for ( int j = 0; j <= m; j++ )
|
||||
matrix[0][j] = j;
|
||||
|
||||
// Step 3
|
||||
for ( int i = 1; i <= n; i++ )
|
||||
{
|
||||
const QChar s_i = source[i - 1];
|
||||
|
||||
// Step 4
|
||||
for ( int j = 1; j <= m; j++ )
|
||||
{
|
||||
const QChar t_j = target[j - 1];
|
||||
|
||||
// Step 5
|
||||
int cost;
|
||||
if ( s_i == t_j )
|
||||
cost = 0;
|
||||
else
|
||||
cost = 1;
|
||||
|
||||
// Step 6
|
||||
const int above = matrix[i - 1][j];
|
||||
const int left = matrix[i][j - 1];
|
||||
const int diag = matrix[i - 1][j - 1];
|
||||
|
||||
int cell = ( ( ( left + 1 ) > ( diag + cost ) ) ? diag + cost : left + 1 );
|
||||
if ( above + 1 < cell )
|
||||
cell = above + 1;
|
||||
|
||||
// Step 6A: Cover transposition, in addition to deletion,
|
||||
// insertion and substitution. This step is taken from:
|
||||
// Berghel, Hal ; Roach, David : "An Extension of Ukkonen's
|
||||
// Enhanced Dynamic Programming ASM Algorithm"
|
||||
// (http://www.acm.org/~hlb/publications/asm/asm.html)
|
||||
if ( i > 2 && j > 2 )
|
||||
{
|
||||
int trans = matrix[i - 2][j - 2] + 1;
|
||||
|
||||
if ( source[ i - 2 ] != t_j ) trans++;
|
||||
if ( s_i != target[ j - 2 ] ) trans++;
|
||||
if ( cell > trans ) cell = trans;
|
||||
}
|
||||
matrix[i][j] = cell;
|
||||
}
|
||||
}
|
||||
|
||||
// Step 7
|
||||
return matrix[n][m];
|
||||
}
|
||||
|
||||
|
||||
static QMutex s_noProxyHostsMutex;
|
||||
static QStringList s_noProxyHosts;
|
||||
|
||||
|
@@ -100,9 +100,10 @@ namespace TomahawkUtils
|
||||
DLLEXPORT QString ageToString( const QDateTime& time, bool appendAgoString = false );
|
||||
DLLEXPORT QString filesizeToString( unsigned int size );
|
||||
DLLEXPORT QString extensionToMimetype( const QString& extension );
|
||||
|
||||
|
||||
DLLEXPORT void msleep( unsigned int ms );
|
||||
DLLEXPORT bool newerVersion( const QString& oldVersion, const QString& newVersion );
|
||||
DLLEXPORT int levenshtein( const QString& source, const QString& target );
|
||||
|
||||
DLLEXPORT NetworkProxyFactory* proxyFactory( bool makeClone = false, bool noMutexLocker = false );
|
||||
DLLEXPORT void setProxyFactory( TomahawkUtils::NetworkProxyFactory* factory, bool noMutexLocker = false );
|
||||
|
Reference in New Issue
Block a user