objective-c - 使用 NSScanner 进行高效的 NSString 解析

标签 objective-c ios ios5 foundation nsscanner

首先,我正在编写一个 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

(数字周围根本没有任何空格,并且斜杠和第二个道路名称之间没有空格)

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

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

我认为使用 NSScanner 可以更高效、更优雅地完成整个过程,但不幸的是,我没有使用此类的必要经验来使其工作。任何建议将不胜感激。

最佳答案

你也可以使用 Regular Expression .

请注意,在 block 中我使用捕获 block ,通过 [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;
}

关于objective-c - 使用 NSScanner 进行高效的 NSString 解析,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10242663/

相关文章:

ios - 无法使用 Alamofire 成功完成带有参数的 GET 请求

iphone - 在 iOS 应用程序中打开网页

iphone - 为 iOS4.3 和 iOS5.0 构建问题

iphone - 如何在 iOS 5 上以横向模式显示视频?

ios - viewForAnnotation 没有被调用

ios - 修剪 NSDate 以仅显示日期

ios - UICollectionView 使用 SDWebImage 滚动

ios - Xcode UI 测试 - 通过 id 在 Webview 中查找元素

iphone - 为相机的每一帧应用一个过滤算法

ios - 委托(delegate)方法在我的应用程序中工作,我如何使它在我的框架中工作?