Use a better data structure to track uniques songs when removing duplicate.
This commit is contained in:
parent
cf22a91c6a
commit
af8e8c753e
|
@ -1114,12 +1114,6 @@ bool Song::IsMetadataEqual(const Song& other) const {
|
|||
d->cue_path_ == other.d->cue_path_;
|
||||
}
|
||||
|
||||
bool Song::IsDuplicate(const Song& other) const {
|
||||
return url() == other.url() ||
|
||||
(title().toLower() == other.title().toLower() &&
|
||||
artist().toLower() == other.artist().toLower());
|
||||
}
|
||||
|
||||
bool Song::IsEditable() const {
|
||||
return d->valid_ && !d->url_.isEmpty() && !is_stream() &&
|
||||
d->filetype_ != Type_Unknown && !has_cue();
|
||||
|
@ -1136,6 +1130,16 @@ uint qHash(const Song& song) {
|
|||
return qHash(song.url().toString()) ^ qHash(song.beginning_nanosec());
|
||||
}
|
||||
|
||||
bool Song::IsSimilar(const Song& other) const {
|
||||
return title().compare(other.title(), Qt::CaseInsensitive) == 0 &&
|
||||
artist().compare(other.artist(), Qt::CaseInsensitive) == 0;
|
||||
}
|
||||
|
||||
uint HashSimilar(const Song& song) {
|
||||
// Should compare the same fields as function IsSimilar
|
||||
return qHash(song.title().toLower()) ^ qHash(song.artist().toLower());
|
||||
}
|
||||
|
||||
bool Song::IsOnSameAlbum(const Song& other) const {
|
||||
if (is_compilation() != other.is_compilation())
|
||||
return false;
|
||||
|
|
|
@ -262,7 +262,7 @@ class Song {
|
|||
// Comparison functions
|
||||
bool IsMetadataEqual(const Song& other) const;
|
||||
bool IsOnSameAlbum(const Song& other) const;
|
||||
bool IsDuplicate(const Song& other) const;
|
||||
bool IsSimilar(const Song& other) const;
|
||||
|
||||
bool operator==(const Song& other) const;
|
||||
|
||||
|
@ -283,5 +283,7 @@ typedef QList<Song> SongList;
|
|||
Q_DECLARE_METATYPE(QList<Song>);
|
||||
|
||||
uint qHash(const Song& song);
|
||||
// Hash function using field checked in IsSimilar function
|
||||
uint HashSimilar(const Song& song);
|
||||
|
||||
#endif // SONG_H
|
||||
|
|
|
@ -62,6 +62,7 @@
|
|||
#include <QtDebug>
|
||||
|
||||
#include <algorithm>
|
||||
#include <unordered_map>
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
using smart_playlists::Generator;
|
||||
|
@ -1919,36 +1920,45 @@ void Playlist::RemoveDeletedSongs() {
|
|||
removeRows(rows_to_remove);
|
||||
}
|
||||
|
||||
struct SongSimilarHash {
|
||||
long operator() (const Song& song) const {
|
||||
return HashSimilar(song);
|
||||
}
|
||||
};
|
||||
|
||||
struct SongSimilarEqual {
|
||||
long operator() (const Song& song1, const Song& song2) const {
|
||||
return song1.IsSimilar(song2);
|
||||
}
|
||||
};
|
||||
|
||||
void Playlist::RemoveDuplicateSongs() {
|
||||
QList<int> rows_to_remove;
|
||||
QHash<Song, int> unique_songs;
|
||||
std::unordered_map<Song, int, SongSimilarHash, SongSimilarEqual> unique_songs;
|
||||
|
||||
for (int row = 0; row < items_.count(); ++row) {
|
||||
PlaylistItemPtr item = items_[row];
|
||||
Song song = item->Metadata();
|
||||
const Song& song = item->Metadata();
|
||||
|
||||
bool found_duplicate = false;
|
||||
QHashIterator<Song, int> iterator(unique_songs);
|
||||
|
||||
while (iterator.hasNext() && !found_duplicate) {
|
||||
iterator.next();
|
||||
Song uniq_song = iterator.key();
|
||||
auto uniq_song_it = unique_songs.find(song);
|
||||
if (uniq_song_it != unique_songs.end()) {
|
||||
const Song& uniq_song = uniq_song_it->first;
|
||||
|
||||
if (song.IsDuplicate(uniq_song)) {
|
||||
if (song.bitrate() > uniq_song.bitrate()) {
|
||||
rows_to_remove.append(unique_songs[uniq_song]);
|
||||
unique_songs.remove(uniq_song);
|
||||
unique_songs.insert(song, row);
|
||||
}
|
||||
else {
|
||||
rows_to_remove.append(row);
|
||||
}
|
||||
found_duplicate = true;
|
||||
if (song.bitrate() > uniq_song.bitrate()) {
|
||||
rows_to_remove.append(unique_songs[uniq_song]);
|
||||
unique_songs.erase(uniq_song);
|
||||
unique_songs.insert(std::make_pair(song, row));
|
||||
} else {
|
||||
rows_to_remove.append(row);
|
||||
}
|
||||
found_duplicate = true;
|
||||
}
|
||||
|
||||
if (!found_duplicate)
|
||||
unique_songs.insert(song, row);
|
||||
if (!found_duplicate) {
|
||||
unique_songs.insert(std::make_pair(song, row));
|
||||
}
|
||||
}
|
||||
|
||||
removeRows(rows_to_remove);
|
||||
|
|
Loading…
Reference in New Issue