4

首先,我正在编写一个 iOS 5 应用程序。例如,假设我有以下字符串:

100 - PARK STREET / JAMES PLACE

我想以最有效(和代码优雅)的方式从这个字符串中提取两个道路名称。我已经尝试过使用[string componentsSeparatedByString...]等的组合,但这变得非常混乱,非常快。此外,它需要大量的条件语句来处理如下情况:

100 - BI-CENTENNIAL DRIVE / JAMES PLACE

[string componentsSeparatedByString:@"-"]因为它包含一个嵌套的连字符,如果我们正在使用并且需要重新组装,它将被拆分。

在某些情况下,字符串的格式可能略有不同,例如:

100- BI-CENTENNIAL DRIVE / JAMES PLACE

(数字和连字符之间没有空格)

100-BI-CENTENNIAL DRIVE /JAMES PLACE

(数字周围完全没有空格,斜线和第二个道路名称之间没有空格)

但是,我们总是可以假设字符串中只有一个斜杠来分隔两个道路名称。

道路名称​​也应该去掉任何前导和尾随空格。

我认为使用 an 可以以更有效和优雅的方式实现整个过程,NSScanner但不幸的是,我没有必要的此类课程的经验来使其工作。任何建议将不胜感激。

4

4 回答 4

3

您也可以使用正则表达式

请注意,在该块中,我使用捕获块,通过[result rangeAtIndex:i].
索引 1 现在将是门牌号,索引 2 将返回第一条街道,索引 3 将返回第二条街道。

#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;
}

第二次编辑

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类的例子。

假设您有一个包含四个值的字符串,并希望将它们转换为 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 代码,我很清楚使用过去 15 年的任何微软开发环境,这将需要一个行代码。

呜呜呜……

于 2013-08-19T20:34:55.950 回答