对数组中的字符串不区分大小写的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?的主要内容,如果未能解决你的问题,请参考以下文章

PHP 数组中的PHP搜索字符串 - 不区分大小写

数组中的PHP搜索字符串-不区分大小写

按字母顺序排序arraylist(不区分大小写)

不区分大小写地检查字符串是不是存在于数组中

C# 怎么把数组中的数据添加到datagridview中

使 Laravel 的 notIn 验证规则不区分大小写