Ух ты, эта проблема раздражала.
Моя настройка следующая. У меня есть поиск, который принимает входные данные и ищет пользователей, сопоставляя имя пользователя или полное имя. Сервер уже возвращал соответствующий порядок, но так как я использую NSFetchedResultsController, мне нужен некоторый дескриптор сортировки. Вот то, что я сделал, что, кажется, работает хорошо. Я добавил новое свойство в свой пользовательский объект с именем matchScore
, и во время CRUD с сервера я получаю оценку MIN()
Левенштейновского расстояния между запросом <-> имя пользователя и запросом <-> полное имя
Теперь у меня есть дескриптор сортировки, который упорядочит по ближайшему совпадению результаты с сервера с запросом пользователя. Код 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
})
Вот категория NSString
, которую я использую, чтобы получить расстояние Левенштейна. https://gist.github.com/iloveitaly/1515464