如何在objective-c中比较自定义sqlite排序规则中的字符?

时间:2013-05-29 06:02:51

标签: ios objective-c c sqlite collation

我在SO上遇到了很多问题(比如this one),但我仍然需要一些帮助。

我需要我的sqlite选择按斯洛文尼亚字母排序(字母č在c之后,字母š在s之后,字母ž在z之后)。

以下是我使用的代码:

static int sqlite3SloCollate(void * foo, int ll, const void *l, int rl,
                                        const void *r){
    NSString *left = [NSString stringWithCharacters:l length:ll];
    NSString *right = [NSString stringWithCharacters:r length:rl];
    //THIS IS WHERE I DON'T KNOW HOW TO COMPARE CHARACTERS
    NSComparisonResult rs = [left compare:right options:NSForcedOrderingSearch];

    return rs;
}

sqlite3_create_collation(database, "SLOCOLLATE", SQLITE_UTF8, NULL, &sqlite3SloCollate);

querySQL = [NSString stringWithFormat: @"SELECT s.id FROM lyrics l INNER JOIN song s ON (l.idSong=s.id) WHERE content LIKE '%%%@%%' GROUP BY s.id ORDER BY s.title COLLATE SLOCOLLATE;",searchString];

我应该使用哪种NSOrdering类型?或者我必须编写自己的比较功能(你能举个例子)吗?

2 个答案:

答案 0 :(得分:1)

我认为这个功能可以帮到你:

- (NSComparisonResult)compare:(NSString *)aString options:(NSStringCompareOptions)mask range:(NSRange)range locale:(id)locale

(来自Apple documentation)。

您可以使用以下方式创建区域设置:

- (id)initWithLocaleIdentifier:(NSString *)string

(来自Apple NSLocale Class Documentation)。

这段代码可以解决问题:

NSRange range = NSMakeRange(0, [left length]);
id locale = [[NSLocale alloc] initWithLocaleIdentifier:@"sl_SI"];
NSComparisonResult rs = [left compare:right options:NSForcedOrderingSearch range:range locale:locale];

我希望这会有所帮助。

答案 1 :(得分:1)

@DCMaxxx的答案大部分都是。加上您需要使用stringWithUTF8String的评论。但还有一些问题。

1)stringWithUTF8String使用以null结尾的c字符串,而sqlite只提供长度且没有空终止的字符串。

2)对于要比较的字符数,我们需要采用最短的长度,而不仅仅是左边的长度。

3)当比较对比较相等时,我们需要考虑哪个字符串更长。

此处为完整代码。我使用NSMutableData对象将长度编码的字符串转换为空终止字符串。如果您倾向于使用直接C代码,它可能更快更容易。

static int sqlite3SloCollate(void * foo, int ll, const void *l, int rl,
                             const void *r){
    NSMutableData* ld = [NSMutableData dataWithBytes:l length:ll+1];
    [ld resetBytesInRange:NSMakeRange(ll, 1)];
    NSString *left = [NSString stringWithUTF8String:[ld bytes]];

    NSMutableData* rd = [NSMutableData dataWithBytes:r length:rl+1];
    [rd resetBytesInRange:NSMakeRange(rl, 1)];    
    NSString *right = [NSString stringWithUTF8String:[rd bytes]];

    NSRange range = NSMakeRange(0, MIN([left length],[right length]));
    id locale = [[NSLocale alloc] initWithLocaleIdentifier:@"sl_SI"];
    NSComparisonResult result = [left compare:right options:0 range:range locale:locale];

    if (result==NSOrderedSame) {
        if (ll>rl) {
            result = NSOrderedDescending;
        } else if (ll<rl) {
            result = NSOrderedAscending;
        }
    }    
    // NSLog(@"Comparison:%@ - %@ - %li",left,right,(long)result);
    return result;
}