如何使用 nspredicate 对非英语字符串进行排序?

Posted

技术标签:

【中文标题】如何使用 nspredicate 对非英语字符串进行排序?【英文标题】:How to sort non-english strings using nspredicate? 【发布时间】:2012-08-05 07:01:21 【问题描述】:

我正在使用排序描述符对获取请求的结果进行排序。

NSFetchRequest* req = [[NSFetchRequest alloc] initWithEntityName:[MyEntity entityName]];
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:@"property" 
                                                           ascending:YES 
                                                            selector:@selector(localizedCompare:)];
req.sortDescriptors = [NSArray arrayWithObject:descriptor];
return [self.managedObjectContext executeFetchRequest:req error:nil];

问题在于以“İ”等非英语字符开头的单词列在列表末尾。这是一个土耳其字母,字母表如下所示:

A、B、C、Ç、D、E、F、G、Ğ、H、I、İ、J、K、L、M、N、O、Ö、P、R、S、Ş、T , U, Ü, V, Y, Z。

所以字母在第 12 位。

我不知道为什么,但是在获取对象后使用比较器是可行的。所以它适用于任何数组,但不适用于获取请求的排序描述符。

【问题讨论】:

【参考方案1】:

在NSFetchedResultsController v.s. UILocalizedIndexedCollation 上查看我的问题的详细信息,我将展示如何使用 UILocalizedIndexedCollat​​ion 正确生成 Alphabet 并使用基于 UILocalizedIndexCollat​​ion 的正确排序方法进行排序。我的问题只是围绕着寻求一种更好的方法来做到这一点。

如果您不使用 UILocalizedIndexCollat​​ion,您应该只使用 localizedStandardCompare:而不是 WWDC 视频中提到的本地化比较进行本地化。

【讨论】:

【参考方案2】:

试试

[NSSortDescriptor alloc] initWithKey:@"property" ascending:YES selector:@selector(localizedCompare:)]

编辑

@Mert 更新了他的问题。现在看来localizedCompare: 对土耳其字母进行了正确排序,但不适用于获取请求。

这是我为测试此问题所做的。也许您可以检查它是否适用于您的环境,然后从那里开始工作:

// Create some entities:
NSArray *a = @[@"İ", @"J", @"Ğ", @"G", @"H", @"I", @"Ç", @"C"];
for (NSString *s in a) 
    MyEntity *e = [NSEntityDescription insertNewObjectForEntityForName:@"MyEntity"
                                                inManagedObjectContext:self.managedObjectContext];
    e.name = s;


// Fetch all entities in sorted order:
NSFetchRequest* req = [[NSFetchRequest alloc] initWithEntityName:@"MyEntity"];
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:@"name"
                                                           ascending:YES
                                                            selector:@selector(localizedCompare:)];
req.sortDescriptors = [NSArray arrayWithObject:descriptor];
NSArray *result = [self.managedObjectContext executeFetchRequest:req error:nil];

“MyEntity”是一个核心数据实体,具有一个字符串类型的属性“名称”。

【讨论】:

它没有用。我也试过改变模拟器的语言。 这很奇怪。如果我使用[myArray sortedArrayUsingSelector:@selector(localizedCompare:)] 对数组进行排序,那么我会得到正确的结果。你能展示你如何设置获取请求的代码吗? 我以几乎相同的方式完成了它(使用获取的结果控制器),它适用于德语变音符号和其他国际字符。顺便说一句:您是否使用 ARC 编译? 我已经尝试过了,但会再次询问您在项目设置中的本地化原生开发区域是什么?是的,我正在使用 ARC 进行编译 localizedCompare 函数从哪里获取语言?【参考方案3】:

我遇到了类似的问题:

[strArr sortedArrayUsingSelector:@selector(localizedCompare:)]

好像

localizedCompare

来电

compare:other options:nil range:NSMakeRange(0, self.length) locale: [NSLocale currentLocale]];

[NSLocale currentLocale] 可能处于混合状态,具体取决于用户的偏好。因此需要根据用户语言创建一个干净的NSLocale

尝试在NSString 上创建一个包含以下内容的类别:

-(NSComparisonResult)currentLocalCompare:(id)other

    NSLocale * currLoc = [NSLocale currentLocale]; //get current locale
    NSLocale * loc = [[NSLocale alloc] initWithLocaleIdentifier:currLoc.localeIdentifier];//lets create a new clean NSLocale based on users prefared langauge
    return [self compare:other options:nil range:NSMakeRange(0, self.length) locale:loc];//compare using clean NSLocale

然后这样称呼它:

[strArr sortedArrayUsingSelector:@selector(currentLocalCompare:)]

【讨论】:

以上是关于如何使用 nspredicate 对非英语字符串进行排序?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用正则表达式搜索忽略 NSPredicate 的某些字符?

核心数据:如何使用 NSPredicate 查找空字段

NSPredicate:如何将字符串视为数字?

使用 NSPredicate 过滤 NSArray 并找到相似的字符串

如何转义 NSPredicate 格式字符串中的尾部反斜杠

如何制作正确过滤本地字符的 NSPredicate?