NSPredicate содержит поиск в строке, содержащей цифры и буквы

Мне нужно использовать NSPredicate для поиска по некоторым объектам Core Data. Но ключ name настраиваемого объекта может содержать как цифры, так и буквы. Строка может выглядеть так: John 1234 Lennonили Ringo Starr. Обычно я бы использовал предикат NSPredicate *predicate = [NSPredicate predicateWithFormat:@"Any name CONTAINS[cd] %@",searchString];

Но если я ищу John Lennon, предикат ничего не возвращает, потому что он не может сравнить, содержит ли он символы John Lennon, поскольку отсутствует 1234. Какие-нибудь подсказки, какой предикат я могу использовать?


person lagos    schedule 15.10.2012    source источник


Ответы (3)


Вы можете токенизировать свой запрос, возможно, так просто, как

NSArray *tokens = [querystring componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];

Затем создайте составной предикат.

NSMutableArray *predarray = [NSMutableArray array];

for(NSString *token in tokens)
{
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"Any name CONTAINS[cd] %@",token];
    [predarray addObject:predicate];
}

NSPredicate *final = [NSCompoundPredicate andPredicateWithSubpredicates:predarray];

И скормите это на свой запрос

В реальной жизни я бы провел небольшую проверку каждого токена, чтобы проверить, будет ли он действительным предикатом и не приведет к сбою или создаст угрозу безопасности. например, уберите специальные символы, такие как "* []"

РЕДАКТИРОВАТЬ: исправлен тип предиката для работы с ситуацией с вопросами.

person Warren Burton    schedule 15.10.2012
comment
Когда я изменил NSCompoundPredicate на andPredicateWithSubPredicates, это сработало как шарм. Потому что orPredicateWithSubPredicates даст ANY name CONTAINS[cd] John OR ANY name CONTAINS[cd] Lennon. В большой базе данных может быть много альтернатив. Но И даст мне только один. - person lagos; 16.10.2012
comment
Это потрясающе! Спасибо - person mikemike396; 03.03.2016

Попробуйте использовать LIKE вместо contains, а затем вы можете использовать подстановочные знаки, например, John * Lennon должен соответствовать строке, которая начинается с John и заканчивается на Lennon с любым количеством других символов между ними. Вы можете использовать ? Вместо этого будет соответствовать только один символ для каждого вопросительного знака, если вы хотите больше контролировать то, что соответствует.

person rdelmar    schedule 15.10.2012

Вы можете разделить строку поиска на массив строк, а затем переключить свой предикат на поиск любой строки в имени:

NSArray *strings = [searchString componentsSeparatedByString:@" "];

NSPredicate *pred = [NSPredicate predicateWithFormat:@"ANY %@ IN name",strings];
person ChrisH    schedule 15.10.2012
comment
С этим предикат ничего не может найти. Я тоже пробовал "ANY name IN %@",strings, но не получилось. - person lagos; 16.10.2012