使用代码
在文本Çınaraltı Café
中搜索文本Ci
NSStringCompareOptions options =
NSCaseInsensitiveSearch |
NSDiacriticInsensitiveSearch |
NSWidthInsensitiveSearch;
NSLocale *locale = [NSLocale localeWithLocaleIdentifier:@"tr"];
NSRange range = [haystack rangeOfString:needle
options:options
range:NSMakeRange(o, haystack.length)
locale:locale];
我认为range.location
等于NSNotFound
。
这与初始Ç上的变音符号没有关系,因为我得到相同的结果搜索alti
,其中唯一奇怪的字符是ı。我也得到一个有效的匹配,搜索包含变音符号(é)的Cafe
。
苹果文档mention this situation作为locale
参数的注释,我认为我正在关注它们。虽然我想我不是因为它不起作用。
如何搜索“i”以匹配“i”和“ı”?
答案 0 :(得分:3)
我不知道这是否有助于作为答案,但也许可以解释为什么会发生这种情况。
我应该指出我不是这方面的专家,但我一直在为自己的目的研究这个问题并且正在做一些研究。
查看Unicode collation chart for latin,ASCII "i" (\u0069)
的等效字符不包括"ı" (\u0131)
,而示例字符串中的所有其他字母都符合您的预期,即:
"c" (\u0063)
包括"Ç" (\u00c7)
"e" (\u0065)
包括"é" (\u00e9)
ı
字符单独列为主要差异至i
。这对土耳其语发言者来说可能没有意义(我不是其中之一),但它是Unicode必须说的,它确实符合你描述的问题的逻辑。
在Chrome中,您可以通过页内搜索查看此操作。在页面中搜索ASCII i
会突出显示其块中的所有字符,但与ı
不匹配。搜索ı
则恰恰相反。
相比之下,MySQL's utf8_general_ci collation table可以根据需要将大写ASCII I
映射到ı
。
所以,在不了解iOS的情况下,我假设它正在使用Unicode标准,并通过此表将所有字符规范化为拉丁语。
关于如何将Çınaraltı
与Ci
匹配 - 如果您无法覆盖整理表,那么您可以只用正则表达式替换搜索字符串中的i
,您可以搜索Ç[iı]
。
答案 1 :(得分:3)
我在Swift 3中为土耳其语字符串搜索编写了一个简单的扩展名。
let turkishSentence = "Türkçe ya da Türk dili, batıda Balkanlar’dan başlayıp doğuda Hazar Denizi sahasına kadar konuşulan Altay dillerinden biridir."
let turkishWannabe = "basLayip"
let shouldBeTrue = turkishSentence.contains(turkishString: turkishWannabe, caseSensitive: false)
let shouldBeFalse = turkishSentence.contains(turkishString: turkishWannabe, caseSensitive: true)
查看
答案 2 :(得分:1)
我这样做了,似乎对我有用..希望它有所帮助!
NSString *cleanedHaystack = [haystack stringByReplacingOccurrencesOfString:@"ı"
withString:@"i"];
cleanedHaystack = [cleanedHaystack stringByReplacingOccurrencesOfString:@"İ"
withString:@"I"];
NSString *cleanedNeedle = [needle stringByReplacingOccurrencesOfString:@"ı"
withString:@"i"];
cleanedNeedle = [cleanedNeedle stringByReplacingOccurrencesOfString:@"İ"
withString:@"I"];
NSUInteger options = (NSDiacriticInsensitiveSearch |
NSCaseInsensitiveSearch |
NSWidthInsensitiveSearch);
NSRange range = [cleanedHaystack rangeOfString:cleanedNeedle
options:options];
答案 3 :(得分:1)
Tim提到,我们可以使用正则表达式来匹配包含i
或ı
的文字。当搜索查找大量字符串时,我也不想添加新字段或更改源数据。所以我最终得到了一个使用正则表达式和NSPredicate
的解决方案。
创建NSString
类别并复制此方法。它返回基本的or
匹配模式。您可以将它与任何接受正则表达式模式的方法一起使用。
- (NSString *)zst_regexForTurkishLettersWithCaseSensitive:(BOOL)caseSensitive
{
NSMutableString *filterWordRegex = [NSMutableString string];
for (NSUInteger i = 0; i < self.length; i++) {
NSString *letter = [self substringWithRange:NSMakeRange(i, 1)];
if (caseSensitive) {
if ([letter isEqualToString:@"ı"] || [letter isEqualToString:@"i"]) {
letter = @"[ıi]";
} else if ([letter isEqualToString:@"I"] || [letter isEqualToString:@"İ"]) {
letter = @"[Iİ]";
}
} else {
if ([letter isEqualToString:@"ı"] || [letter isEqualToString:@"i"] ||
[letter isEqualToString:@"I"] || [letter isEqualToString:@"İ"]) {
letter = @"[ıiIİ]";
}
}
[filterWordRegex appendString:letter];
}
return filterWordRegex;
}
因此,如果搜索字为Şırnak
,则会针对区分大小写的情况创建Ş[ıi]rnak
,针对不区分大小写的搜索创建Ş[ıiIİ]rnak
。
以下是可能的用法。
NSString *testString = @"Şırnak";
// First create your search regular expression.
NSString *searchWord = @"şır";
NSString *searchPattern = [searchWord zst_regexForTurkishLettersWithCaseSensitive:NO];
// Then create your matching pattern.
NSString *pattern = searchPattern; // Direct match
// NSString *pattern = [NSString stringWithFormat:@".*%@.*", searchPattern]; // Contains
// NSString *pattern = [NSString stringWithFormat:@"\\b%@.*", searchPattern]; // Begins with
// NSPredicate
// c for case insensitive, d for diacritic insensitive
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"self matches[cd] %@", pattern];
if ([predicate evaluateWithObject:testString]) {
// Matches
}
// If you want to filter an array of objects
NSArray *matchedCities = [allAirports filteredArrayUsingPredicate:
[NSPredicate predicateWithFormat:@"city matches[cd] %@", pattern]];
您也可以使用NSRegularExpression
,但我认为使用NSPredicate
使用案例和变音符号不敏感搜索要简单得多。