7

コードを使用しÇı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.locationequalsを取得しNSNotFoundます。

最初の Ç の分音符号とは関係ありません。なぜならalti、唯一の奇数文字が ı である場所を検索しても同じ結果が得られるからです。Cafeまた、分音符号 (é) を含む有効な一致検索も取得します。

アップルのドキュメントでは、この状況localeがパラメーターに関するメモとして言及されており、私はそれらに従っていると思います。私はそうではないと思いますが、それは機能していないからです。

「i」と「ı」の両方に一致するように「i」を検索するにはどうすればよいですか?

4

4 に答える 4

4

これが答えとして役立つかどうかはわかりませんが、おそらくそれが起こっている理由を説明しています.

私はこの問題の専門家ではないことを指摘しておく必要がありますが、私は自分自身の目的のためにこれを調査し、いくつかの調査を行ってきました.

latin の Unicode 照合チャートを見ると、ASCII に相当する文字に"i" (\u0069)は が含まれていませんが"ı" (\u0131)、サンプル文字列の他のすべての文字は期待どおりです。

  • "c" (\u0063) 含む_"Ç" (\u00c7)
  • "e" (\u0065) 含む_"é" (\u00e9)

このı文字は、 との主な違いとして個別にリストされていiます。それはトルコ語を話す人には意味をなさないかもしれませんが(私はそうではありません)、それはUnicodeがそれについて言わなければならないことであり、あなたが説明する問題の論理に適合します.

Chrome では、ページ内検索でこれを実際に確認できます。ページ内で ASCII を検索するとi、そのブロック内のすべての文字が強調表示され、一致しませんı。検索ıはその逆です。

対照的に、MySQL の utf8_general_ci 照合テーブルは、必要に応じて大文字の ASCIIIをマップıします。

したがって、iOS について何も知らなくても、Unicode 標準を使用し、この表によってすべての文字をラテン語に正規化していると思います。

照合方法については、照合テーブルÇınaraltıCiオーバーライドできない場合は、おそらくi検索文字列を正規表現に置き換えることができるため、代わりに検索しÇ[iı]ます。

于 2013-07-25T00:34:10.067 に答える
1

ティムが言及しているように、正規表現を使用して、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方がはるかに簡単だと思います。

于 2014-09-23T10:45:46.203 に答える