在NSFetchedResultsController中进行自定义排序
花费数小时后,我发现无法在下面的文章中用SQLite支持的NSFetchedResultsController中进行自定义排序。
NSFetchedResultsController自定义排序没有被调用
但是,我找不到我的问题的实际解决方案。
这是我想要做的。
背景:
我有一个英文字典数据库(只是一个简单的单词列表 - 非常大)在CoreData中。 单词使用NSFetchedResultsController显示在UITableView中。
UITableView有一个关联的搜索栏。 当用户在搜索栏中输入字符串时,UITableView将显示已过滤的单词列表。
为什么我需要自定义排序:
当用户输入一个字符串时,假设它是bre
,我将它改为正则表达式, b.*r.*e.*
并将其用作NSPredicate,然后执行Fetch。 因此,在表格视图中将显示“裸露”和“中断”等所有单词。
默认情况下,这些单词以字母顺序显示。 因此, bare
会在break
之前来临。
我想break
来之前bare
搜索列表上,因为前三个字符break
完全匹配到什么用户输入。
可能的想法:
bre.*
对bre.*
, br.+e.*
, b.+r.+e.*
执行bre.*
并合并它们。 这两个想法看起来不太整齐。
我很感激您是否可以为这类问题提出任何已知的典型解决方案。
您可以考虑的另一种方法是使用瞬态属性来装饰结果以指示匹配类型,然后使用该瞬态属性作为第一个排序描述符。
这需要遍历所有结果,再次比较字符串并设置属性。 如果你期望得到很长的一组结果,那么使用一个数组可能会很容易。
如果您需要高效地处理大型结果集,建议使用两种排序描述符,一种只返回精确匹配,另一种仅返回非精确匹配。 然后显示第一个结果和第二个结果。 使用复合谓词应该可以完成。
哇,这个问题很烦人。
我的设置如下。 我有一个搜索需要输入并通过匹配用户名或全名查找用户。 服务器已经返回适当的顺序,但由于我使用NSFetchedResultsController我需要一些排序描述符这是我做的似乎工作得很好。 我向我的用户实体添加了一个名为matchScore
的新属性,并在服务器的CRUD期间获得查询< - >用户名和查询< - >全名的MIN()
Levenshtein距离得分
我现在有一个排序描述符,它将根据用户查询中最接近的服务器匹配结果进行排序。 代码是rubymotion,但应该仍然可读。
sortDescriptors = []
sortDescriptors << NSSortDescriptor.sortDescriptorWithKey("matchScore", ascending:true)
使用新的排序描述符,我现在可以获取“不太理想”的结果,并且仍然保持最接近的匹配。 我现在可以避免@ Jaemin的一些潜在解决方案,这些解决方案涉及复杂的结果聚合,以避免自定义排序无法正常工作。
request.predicate = NSPredicate.predicateWithFormat("(username MATCHES[cd] %@) OR (username BEGINSWITH[cd] %@) OR (name CONTAINS[cd] %@)", argumentArray:[searchString, searchString, searchString])
现在在服务器的CRUD上生成匹配分数。
usersContext.performBlock(lambda{
restUsers.each do |restUser|
user = User.entityWithRestModel(restUser, usersContext)
user.matchScore = [query.compareWithWord(user.username, matchGain:10, missingCost:1), query.compareWithWord(user.name, matchGain:10, missingCost:1].min
puts "u:#{user.username} <-> q:#{query} score:#{user.matchScore}"
end
})
这里是我用来获得Levenshtein距离的NSString
类别。 https://gist.github.com/iloveitaly/1515464
上一篇: Customized sort in NSFetchedResultsController
下一篇: How to use NSFetchedResultsController and UISearchDisplayController