mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-08-14 01:54:07 +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
|
// result values
|
||||||
const QString rArtistname = r->artist()->sortname();
|
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() );
|
const QString rTrackname = DatabaseImpl::sortname( r->track() );
|
||||||
|
|
||||||
// normal edit distance
|
// normal edit distance
|
||||||
int artdist = levenshtein( m_artistSortname, rArtistname );
|
int artdist = TomahawkUtils::levenshtein( m_artistSortname, rArtistname );
|
||||||
int albdist = levenshtein( m_albumSortname, rAlbumname );
|
int albdist = TomahawkUtils::levenshtein( m_albumSortname, rAlbumname );
|
||||||
int trkdist = levenshtein( m_trackSortname, rTrackname );
|
int trkdist = TomahawkUtils::levenshtein( m_trackSortname, rTrackname );
|
||||||
|
|
||||||
// max length of name
|
// max length of name
|
||||||
int mlart = qMax( m_artistSortname.length(), rArtistname.length() );
|
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 artistTrackname = DatabaseImpl::sortname( fullTextQuery() );
|
||||||
const QString rArtistTrackname = DatabaseImpl::sortname( r->artist()->name() + " " + r->track() );
|
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() );
|
int mlatr = qMax( artistTrackname.length(), rArtistTrackname.length() );
|
||||||
float dcatr = (float)( mlatr - atrdist ) / mlatr;
|
float dcatr = (float)( mlatr - atrdist ) / mlatr;
|
||||||
|
|
||||||
@@ -922,83 +922,3 @@ Query::infoSystemFinished( QString target )
|
|||||||
|
|
||||||
emit updated();
|
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;
|
QID id() const;
|
||||||
|
|
||||||
/// sorter for list of results
|
/// 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)
|
/// true when a perfect result has been found (score of 1.0)
|
||||||
bool solved() const { return m_solved; }
|
bool solved() const { return m_solved; }
|
||||||
@@ -221,7 +221,6 @@ private:
|
|||||||
void checkResults();
|
void checkResults();
|
||||||
|
|
||||||
void updateSortNames();
|
void updateSortNames();
|
||||||
static int levenshtein( const QString& source, const QString& target );
|
|
||||||
|
|
||||||
void parseSocialActions();
|
void parseSocialActions();
|
||||||
|
|
||||||
|
@@ -336,6 +336,86 @@ msleep( unsigned int ms )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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 QMutex s_noProxyHostsMutex;
|
||||||
static QStringList s_noProxyHosts;
|
static QStringList s_noProxyHosts;
|
||||||
|
|
||||||
|
@@ -103,6 +103,7 @@ namespace TomahawkUtils
|
|||||||
|
|
||||||
DLLEXPORT void msleep( unsigned int ms );
|
DLLEXPORT void msleep( unsigned int ms );
|
||||||
DLLEXPORT bool newerVersion( const QString& oldVersion, const QString& newVersion );
|
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 NetworkProxyFactory* proxyFactory( bool makeClone = false, bool noMutexLocker = false );
|
||||||
DLLEXPORT void setProxyFactory( TomahawkUtils::NetworkProxyFactory* factory, bool noMutexLocker = false );
|
DLLEXPORT void setProxyFactory( TomahawkUtils::NetworkProxyFactory* factory, bool noMutexLocker = false );
|
||||||
|
Reference in New Issue
Block a user