如何为 NSPredicate 连接两个字符串,即名字和姓氏
Posted
技术标签:
【中文标题】如何为 NSPredicate 连接两个字符串,即名字和姓氏【英文标题】:How to join two strings for NSPredicate, ie firstname and lastname 【发布时间】:2012-12-21 05:42:24 【问题描述】:我有一个 Person
对象,它有两个 NSString
属性; firstName and lastName
。
我目前正在使用NSPredicate
,如下所示:
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(firstName contains[cd] %@) OR (lastName contains[cd] %@)", searchText, searchText];
例如,假设我正在搜索名称"John Smith"
。如果我在搜索栏中输入"Joh"
,那么John Smith
将作为一个选项出现。这很好,但如果我输入"John Sm"
,它将变为空白。
我如何在predicate
中加入名字和姓氏,所以如果我正在搜索"John Sm"
,那么John Smith
仍然会作为一个选项出现。
我希望这是有道理的。谢谢。
编辑:
为了进一步说明,我使用了SearchDisplayController
委托方法:
-(void)filterContentForSearchText:(NSString *)searchText scope:(NSString *)scope;
我正在使用predicate
,如下所示:
newArray = [personObjectArray filteredArrayUsingPredicate:predicate];
【问题讨论】:
查看此处以提供完整信息developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/… 我已经阅读了,但我仍然不明白该怎么做。 您可以更好地使用字典或数组,以便我们轻松实现它 NSArray* ar = [NSArray arrayWithObjects:@"on call", @"I'm on call", @"lala", @"On call", nil]; NSArray* filt = [ar filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"self like[c] 'on call'"]]; NSLog([过滤描述]); //输出“on call”、“on call” 我明白这一点,但我有一个动态的对象数组,我想用我的两个 NSString 对象的属性与 searchText 进行比较。 【参考方案1】:试试这个,
NSString *text = @"John Smi";
NSString *searchText = [text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
NSArray *array = [searchText componentsSeparatedByString:@" "];
NSString *firstName = searchText;
NSString *lastName = searchText;
NSPredicate *predicate = nil;
if ([array count] > 1)
firstName = array[0];
lastName = array[1];
predicate = [NSPredicate predicateWithFormat:@"(firstName CONTAINS[cd] %@ AND lastName CONTAINS[cd] %@) OR (firstName CONTAINS[cd] %@ AND lastName CONTAINS[cd] %@)", firstName, lastName, lastName, firstName];
else
predicate = [NSPredicate predicateWithFormat:@"firstName CONTAINS[cd] %@ OR lastName CONTAINS[cd] %@", firstName, lastName];
NSArray *filteredArray = [people filteredArrayUsingPredicate:predicate];
NSLog(@"%@", filteredArray);
输出:
(
firstName = John;
lastName = Smith;
)
这里的文本代表搜索到的文本。上面的好处是,即使你通过text = @"Smi Joh";
或者text = @"John ";
或者text = @" smi";
或者text = @"joh smi ";
,它仍然会显示上面的输出。
【讨论】:
谢谢你的作品很好,除了一个小问题。假设我正在输入带有空格的“john”,在我开始输入姓氏之前不会出现任何结果,有没有办法在搜索栏中仍然显示带有“john”的 John Smith? 这对我来说也很好用。在发布之前,我已经对此进行了测试。我想你错过了NSString *text = @"john "; NSString *searchText = [text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
我确定你在过滤之前没有对搜索文本做第二行。基本上,您需要在进行过滤时删除任何前导或尾随空格,否则它将失败。所以如果你不使用第二行,它会失败。
啊,是的,它工作正常,我将我的名字和姓氏字符串初始化为错误的字符串。对不起!但是谢谢你,你帮了我很大的忙,我花了很长时间努力做到这一点!
这不起作用。例如,如果用户键入 John Smith blah blah,它将显示 John Smith。这在代码中很清楚,因为一旦字符串组件超过 1([数组计数] > 1),您仍然只使用数组 [0] 和数组 [1]。最好的解决方法是在你的对象中实现一个方法全名(或者一个类别,如果它是一个 nsmanagedobject),然后使用 predicateWithBlock。【参考方案2】:
上面建议的解决方案不适用于包含两个以上单词的搜索字符串。这是 swift 中更彻底的实现。如果您的目标是跨姓名、电子邮件、电话号码等实现全文搜索,此解决方案还允许在记录上添加更多字段。在这种情况下,只需将 NSPredicate 更新为 OR newField CONTAINS[cd] %@
并确保添加额外的$0 在字符串替换列表中。
let searchText = search.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet())
let words = searchText.componentsSeparatedByCharactersInSet(NSCharacterSet.whitespaceCharacterSet())
let predicates = words.map NSPredicate(format: "firstName CONTAINS[cd] %@ OR lastName CONTAINS[cd] %@", $0,$0)
let request = NSFetchRequest()
request.predicate = NSCompoundPredicate(type: NSCompoundPredicateType.AndPredicateType, subpredicates: predicates)
【讨论】:
我迟到了几年,但是。您的答案是唯一通用的答案 似乎是最好的答案!【参考方案3】:您可以将字段连接成两个公共字段(firstLastName 和 lastFirstName)
- (NSString *)firstLastName
return [NSString stringWithFormat:@"%@ %@", self.firstName, self.lastName];
- (NSString *)lastFirstName
return [NSString stringWithFormat:@"%@ %@", self.lastName, self.firstName];
然后使用 'contains[cd]' 过滤此字段
[NSPredicate predicateWithFormat:@"(firstLastName contains[cd] %@) OR (lastFirstName contains[cd] %@)" , self.searchBar.text, self.searchBar.text];
【讨论】:
以上是关于如何为 NSPredicate 连接两个字符串,即名字和姓氏的主要内容,如果未能解决你的问题,请参考以下文章
如何为 CoreData 多对多关系编写 NSPredicate
如何为可以返回 nil 的 NSPredicate 创建惰性 var