我正在寻找一种算法,也许是启发式算法来解决以下问题。
是否可以使用搜索功能枚举集合中的所有项目? 是否有任何已知的算法/启发式方法可以做到这一点?
例如,根据以下条件:
搜索功能的伪实现如下所示:
List<Song> FindSongs(string searchText)
{
var allSongs = LoadAllSongsFromDB();
var allSongsOrderedBySongOrder = allSongs.OrderBy(x => x.SongOrder);
var matchingSongs = allSongsInDatabase.Where(song => searchText == null || song.Title.Contains(searchText));
var topHundred = matchingSongs.Take(100);
return topHundred.AsList();
}
class Song
{
public int Id;
public string Title;
public int SongOrder;
}
答案 0 :(得分:0)
首先搜索单个字母。例如,搜索“ A”可能会返回100首歌曲,但是搜索“ Z”可能会返回不到100首歌曲。
然后为每个返回100首歌曲的字母添加另一个字母。例如,假设搜索“ A”返回100首歌曲,则搜索“ AA”,“ AB”,“ AC”等。
任何返回100首歌曲的搜索都需要通过添加另一个字母来完善。返回少于100首歌曲的搜索已完成:删除重复的歌曲可以将其添加到输出列表中。
答案 1 :(得分:0)
如果存在 数据库,则最好让数据库负责过滤,而不是在代码中进行过滤-如果数据库进行过滤,则不进行过滤必须将所有歌曲发送到您的代码中,这样既节省了时间,又不会使网络过载(想象许多用户同时执行此操作)。数据库还可以在文本字段上建立索引(尽管它们通常不会费心构建对于该用例最有用的索引),因此它们也可以比代码更有效或更快速地找到文本。
在数据库中排名前100名将再次节省时间和网络流量,因此我的伪代码(受Java JPA启发)将简单地让数据库完成所有工作:
PreparedStatement queryByTitle = myDatabase.prepareQuery(
"""SELECT *
FROM Songs
WHERE title LIKE '%:partOfTitle%'
ORDER BY songOrder
LIMIT 100"""
).withStringParameter("partOfTitle");
PreparedStatement queryWithoutTitle = myDatabase.prepareQuery(
"""SELECT *
FROM Songs
ORDER BY songOrder
LIMIT 100""")
List<Song> getSongs(String partOfTitle) {
if (partOfTitle.isEmpty()) {
return myConnection.executePreparedQuery(queryWithoutTitle));
} else {
return myConnection.executePreparedQuery(
queryWithTitle, partOfTitle));
}
}
如果您需要使用数据库中返回的大量歌曲来执行代码中的所有操作,则您所做的任何事情都最多为O(返回的歌曲数)(因为这是获得大型歌曲的代价)首先是数据库中的列表),因此没有哪种O(n)算法会比其他任何算法都快得多。
如果没有 数据库,并且您始终将本地内容存储在一个大列表中,那么您可以比O(n)做得更好