4

まず、iOS5アプリを作成しています。例として、次の文字列があるとします。

100 - PARK STREET / JAMES PLACE

この文字列から2つの道路名を、可能な限り最も効率的な(そしてコードにエレガントな)方法で抽出したいと思います。使用などの組み合わせを試し[string componentsSeparatedByString...]ましたが、これは非常に面倒で、すぐになります。さらに、次のような状況を処理するには、大量の条件ステートメントが必要です。

100 - BI-CENTENNIAL DRIVE / JAMES PLACE

これにはネストされたハイフンが含まれているため、使用していて[string componentsSeparatedByString:@"-"]再アセンブリが必要な場合は分割されます。

次のように、文字列の形式がわずかに異なる場合もあります。

100- BI-CENTENNIAL DRIVE / JAMES PLACE

(数字とハイフンの間にスペースがない)

100-BI-CENTENNIAL DRIVE /JAMES PLACE

(番号を囲むスペースがまったくないことと、スラッシュと2番目の道路名の間にスペースがないことを組み合わせる)

ただし、2つの道路名を区切る文字列にはスラッシュが1つしかないことを常に想定できます。

道路名には、先頭と末尾のスペースも削除する必要があります。

このプロセス全体は、より効率的でエレガントな方法で可能になると思いましたNSScannerが、残念ながら、このクラスを機能させるために必要な経験がありません。任意の提案をいただければ幸いです。

4

4 に答える 4

3

正規表現を使用することもできます。

ブロックでは、を介してキャプチャブロックを使用していることに注意してください[result rangeAtIndex:i]
インデックス1は家番号になり、インデックス2は最初の通りを返し、3は2番目の通りを返します。

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[])
{

    @autoreleasepool {
        NSArray *streets = [NSArray arrayWithObjects:@"100 - PARK STREET / JAMES PLACE", @"100 - BI-CENTENNIAL DRIVE / JAMES PLACE", @"100- BI-CENTENNIAL DRIVE / JAMES PLACE", @"100-BI-CENTENNIAL DRIVE /JAMES PLACE", nil];

        NSString *text = [streets componentsJoinedByString:@" "];
        NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"(\\d+) {0,1}- {0,1}(\\D+) *\\/ *(\\D+)" options:NSRegularExpressionCaseInsensitive error:nil];

        [regex enumerateMatchesInString:text options:0 
                                  range:NSMakeRange(0, [text length]) 
                             usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) 
        {
            for (int i = 1; i< [result numberOfRanges] ; i++) {
                NSLog(@"%@", [text substringWithRange:[result rangeAtIndex:i]]);
            }
        }];
    }
    return 0;
}

出力:

100
PARK STREET 
JAMES PLACE 
100
BI-CENTENNIAL DRIVE 
JAMES PLACE 
100
BI-CENTENNIAL DRIVE 
JAMES PLACE 
100
BI-CENTENNIAL DRIVE 
JAMES PLACE

コメントに応じて編集する

int main (int argc, const char * argv[])
{

    @autoreleasepool {
        NSArray *streets = [NSArray arrayWithObjects:@"100 - PARK STREET / JAMES PLACE", @"100 - BI-CENTENNIAL DRIVE / JAMES PLACE", @"100- BI-CENTENNIAL DRIVE / JAMES PLACE", @"100-BI-CENTENNIAL DRIVE /JAMES PLACE",@"100 - PARK STREET", nil];

        NSRegularExpression *regex1 = [NSRegularExpression regularExpressionWithPattern:@"(\\d+) *- *([^\\/]+) *$" options:NSRegularExpressionCaseInsensitive error:nil];
        NSRegularExpression *regex2 = [NSRegularExpression regularExpressionWithPattern:@"(\\d+) *- *([^\\/]+) *\\/ *([^\\/]+) *$" options:NSRegularExpressionCaseInsensitive error:nil];
        for (NSString *text in streets) {                        
            NSRegularExpression *regex = ([regex1 numberOfMatchesInString:text options:NSRegularExpressionCaseInsensitive range:NSMakeRange(0, [text length])]) ? regex1 : regex2;
            [regex enumerateMatchesInString:text options:0 
                                      range:NSMakeRange(0, [text length]) 
                                 usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) 
             {
                 for (int i = 1; i< [result numberOfRanges] ; i++) {
                     NSLog(@"%@", [text substringWithRange:[result rangeAtIndex:i]]);
                 }

             }];
        }
    }
    return 0;
}

2番目の編集

int main (int argc, const char * argv[])
{

    @autoreleasepool {
        NSArray *streets = [NSArray arrayWithObjects:   @"100 - PARK STREET / JAMES PLACE", 
                                                        @"100 - BI-CENTENNIAL DRIVE / JAMES PLACE", 
                                                        @"100- BI-CENTENNIAL DRIVE / JAMES PLACE", 
                                                        @"100-BI-CENTENNIAL DRIVE /JAMES PLACE",
                                                        @"100 - PARK STREET",
                                                        @"100 - PARK STREET / ",
                                                        @"100 - PARK STREET/ ",
                                                        @"100 - PARK STREET/",
                            nil];

        NSRegularExpression *regex1 = [NSRegularExpression regularExpressionWithPattern:@"(\\d+) *- *([^\\/]+) *$" options:NSRegularExpressionCaseInsensitive error:nil];
        NSRegularExpression *regex2 = [NSRegularExpression regularExpressionWithPattern:@"(\\d+) *- *([^\\/]+) *\\/ *([^\\/]*) *$" options:NSRegularExpressionCaseInsensitive error:nil];
        for (NSString *text in streets) { 

            text= [text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
            NSLog(@"\n>%@<", text);
            NSRegularExpression *regex = ([regex1 numberOfMatchesInString:text options:NSRegularExpressionCaseInsensitive range:NSMakeRange(0, [text length])]) ? regex1 : regex2;
            [regex enumerateMatchesInString:text options:0 
                                      range:NSMakeRange(0, [text length]) 
                                 usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) 
             {
                 for (int i = 1; i< [result numberOfRanges] ; i++) {
                     NSLog(@"%@", [text substringWithRange:[result rangeAtIndex:i]]);
                 }

             }];
        }
    }
    return 0;
}
于 2012-04-20T09:03:35.730 に答える
1

私のブラウザでコーディングしただけです:

NSString* line = @"100- BI-CENTENNIAL DRIVE / JAMES PLACE";
NSScanner* scanner = [NSScanner scannerWithString:line];
NSString* number;
if (![scanner scanUpToString:@"-" intoString:&number])
    /* handle parse failure */;
NSString* firstRoad;
if (![scanner scanUpToString:@"/" intoString:&firstRoad])
    /* handle parse failure */;
NSString* secondRoad = [str substringFromIndex:[scanner scanLocation]];

結果の文字列からトリミングするための追加の空白がある場合があります。

于 2012-04-20T08:54:57.243 に答える
0

これはNSRegularExpressionの仕事のように見えます。

私はREのようなものだと思います

^[0-9]+ *- *(.*)$

あなたが望むものと一致します。

于 2012-04-20T08:48:40.120 に答える
-1

この恐ろしい小さなNSScannerクラスを使用する別の例を次に示します。

4つの値を含む文字列があり、それらをCGRectに変換したいとします。

NSString* stringToParse = @"10, 20, 600, 150";             
CGRect rect = [self stringToCGRect:stringToParse];

NSLog(@"Rectangle: %.0f, %.0f, %.0f, %.0f", rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);

これを行うには、次のような厄介な小さな関数を記述します。

-(CGRect)stringToCGRect:(NSString*)stringToParse
{
    NSLog(@"Parsing the string: %@", stringToParse);
    int x, y, wid, hei;

    NSString *subString;
    NSScanner *scanner = [NSScanner scannerWithString:stringToParse];
    [scanner scanUpToCharactersFromSet:[NSCharacterSet decimalDigitCharacterSet] intoString:nil];
    [scanner scanCharactersFromSet:[NSCharacterSet decimalDigitCharacterSet] intoString:&subString];
    x = [subString integerValue];

    [scanner scanUpToCharactersFromSet:[NSCharacterSet decimalDigitCharacterSet] intoString:nil];
    [scanner scanCharactersFromSet:[NSCharacterSet decimalDigitCharacterSet] intoString:&subString];
    y = [subString integerValue];

    [scanner scanUpToCharactersFromSet:[NSCharacterSet decimalDigitCharacterSet] intoString:nil];
    [scanner scanCharactersFromSet:[NSCharacterSet decimalDigitCharacterSet] intoString:&subString];
    wid = [subString integerValue];

    [scanner scanUpToCharactersFromSet:[NSCharacterSet decimalDigitCharacterSet] intoString:nil];
    [scanner scanCharactersFromSet:[NSCharacterSet decimalDigitCharacterSet] intoString:&subString];
    hei = [subString integerValue];

    CGRect rect = CGRectMake(x, y, wid, hei);
    return rect;
}

私の否定性を許してください、しかし私は疲れています、それは夜の午後10時30分です、そして私はこのようなObjective-Cコードを書かなければならないことを軽蔑します。コードの行。

Grrrr...。

于 2013-08-19T20:34:55.950 に答える