1

我在这里遇到了很多关于 SO(比如这个)的问题,但我仍然需要一些帮助。

我需要我的 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 类型?还是我必须编写自己的比较函数(你能给我一个例子)?

4

2 回答 2

1

@DCMaxxx 答案包含大部分内容。加上您需要使用的注释stringWithUTF8String。但还有一些问题。

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

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;
}
于 2014-07-31T18:15:45.633 回答
1

我认为这个功能可能会帮助你:

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

(来自Apple 文档)。

您可以使用以下方法创建语言环境:

- (id)initWithLocaleIdentifier:(NSString *)string

(来自Apple NSLocale 类文档)。

这段代码应该可以解决问题:

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

我希望这将有所帮助。

于 2013-05-29T07:33:52.240 回答