对数组中的字符串不区分大小写的NSPredicate?
Posted
技术标签:
【中文标题】对数组中的字符串不区分大小写的NSPredicate?【英文标题】:Case insensitive NSPredicate for strings from an array? 【发布时间】:2010-01-06 22:58:56 【问题描述】:我有一种情况,我想通过用户名键从我的核心数据存储中获取对象,但我希望比较不区分大小写。我的谓词是这样的:
username IN $usernames
然后,我使用一组字符串进行变量替换,这些字符串是我要查找的用户名。它有效,但区分大小写。我想做这样的事情,我想:
username IN[c] $usernames
不幸的是,这似乎不起作用。字符串比较必须仍然以区分大小写的方式进行。 (我没有收到关于它是不受支持的查询的错误消息。)
是否有不同的方式来编写这个谓词,以便它按照我需要的方式工作,或者我只是在这里遗漏了一些明显的东西?
【问题讨论】:
您是通过谓词构建器还是直接在代码中构建谓词? 这是一个存储在数据模型中的 Fetch Request。 【参考方案1】:在对 SQLite 存储执行 fetch 时,显然忽略了 IN 运算符上的 case 修饰符。 (您在问题中省略了商店类型。)
我建议针对文档提交错误,以便记录此限制/行为。
我还建议在错误报告器中提交功能请求,以便将来支持。
与此同时,您必须从数据模型中提取获取请求并以编程方式构建它。您可以构建一个复合谓词 OR 谓词,为您的每个值执行不区分大小写的相等匹配(并测试它是否满足您的性能需求。)
请注意,如果您支持 10.6 之前的操作系统目标,则不支持 == 上的大小写修饰符,在这种情况下,将需要另一个替代解决方案。
【讨论】:
最后一点,当用作谓词字符串时,您的意思是 == 吗?以编程方式构建谓词时它仍然有效吗?我的目标是 10.5。 在10.5上测试后,好像不行了。该死!看来我唯一的选择是构建一个类似的表达式:“用户名包含 [cd] $u AND $u 包含 [cd] 用户名”。叹息。 没有。即使使用两个 CONTAINS 也不起作用,因为我的整体表达式是一堆其他谓词的 OR,而且似乎我不能有一个包含 AND 谓词的 OR 集。废话。在这一切都错了之后,我改用 LIKE[cd] 并转义 * 和 ?我的输入字符串中的字符。奇迹般有效。谓词处理中似乎有相当多的限制...... LIKE[c] 和转义 * 和 ?是必须在 10.5 上部署时的典型解决方案。【参考方案2】:您可以尝试ANY $usernames LIKE[c] username
之类的方法。我已经做了类似的事情,而不是变量替换,我只有一个像“persons.name”这样的关键路径,并且该谓词对我有用。不确定它是否与那里的变量而不是关键路径有什么不同,但值得一试。
【讨论】:
不幸的是,该谓词不适用于 SQLite 存储。 (未实现的 SQL 生成。)在它确实起作用的情况下,请注意确保字符串 sin $usernames 有文字 LIKE 通配符转义。【参考方案3】:这是另一种解决方法,但需要您更改 MOM。
使用户名成为一个完整的实体。在用户名和其他实体之间创建反向关系。
现在对于获取请求,将实体设置为“用户名”,然后运行此谓词(假设有“名称”属性和“父”属性):
[NSPredicate predicateWithFormat:"(name like[c] %@) && (parent == %@)", theUserName, theParentObject]
这可能有点矫枉过正,但可以让您根据需要运行搜索。
【讨论】:
【参考方案4】:虽然这个问题已经有好几年了,但我只是偶然发现了同样的问题并像这样解决了它:
NSArray *values = @[@"FOO", @"bar" ,@"lorem"];
NSString *predicate;
predicate = @"value LIKE[cd] '";
predicate = [predicate stringByAppendingString:
[values componentsJoinedByString:
@"' OR value LIKE[cd] '"]];
predicate = [predicate stringByAppendingString:@"'"];
NSLog(@"%@", predicate);
// Output:
// value LIKE[cd] 'FOO' OR value LIKE[cd] 'bar' OR value LIKE[cd] 'lorem'
这会从值列表中创建一个静态谓词表达式。也许它会对某人有用。
更新 2:
实际上,下面的更新解决方案似乎不适用于 sqlite 并产生一个
'NSInvalidArgumentException',
reason: 'unimplemented SQL generation for predicate : ... (bad LHS)'
我认为对于数组/dict/set 比较和IN
,运算符左侧只允许使用键。
更新:
在对表达式和谓词进行了一些研究之后,我发现了另一种方法,似乎效果很好:
NSPredicate *predicate =
[NSPredicate predicateWithFormat:
@"lowercase(value) IN %@", values];
这使用函数表达式lowercase:
来获取值的小写表示。剩下要做的就是确保values
的所有条目都是小写的,并且您将能够使用不区分大小写的IN
表达式。
【讨论】:
以上是关于对数组中的字符串不区分大小写的NSPredicate?的主要内容,如果未能解决你的问题,请参考以下文章