【问题标题】:NSString : String extraction from a comma Separated NSStringNSString :从逗号分隔的 NSString 中提取字符串
【发布时间】:2013-04-24 22:17:03
【问题描述】:

以下是我返回的两个用逗号分隔的字符串示例:

NSString *placeResult = @"111 Main Street, Cupertino, CA"

或者有时结果包含地名:

NSString *placeResult = @"Starbucks, 222 Main Street, Cupertino, CA"

检查上面的字符串以查看它是否以名称或街道地址开头的最佳方法是什么?

如果它确实以名称开头(即上面第二个示例中的星巴克”),我想提取名称并将其存储到另一个变量中。因此提取后的字符串将是:

NSLog (@"%s", placeResult);

日志将打印:

"222 Main Street, Cupertino, CA" 

另一个字符串现在将在其中存储@"Starbucks":

NSLog (@"%s", placeName);

日志将打印:

"Starbucks" 

重要提示:提取后我不能丢失逗号分隔。

谢谢!

【问题讨论】:

    标签: ios objective-c nsstring


    【解决方案1】:

    利用NSDataDetectorNSTextCheckingResult

    NSDataDetector *detector = [NSDataDetector dataDetectorWithTypes:NSTextCheckingTypeAddress error:nil];
    NSString *str = @"Starbucks, 222 Main Street, Cupertino, CA";
    NSArray *matches = [detector matchesInString:str options:0 range:NSMakeRange(0, str.length)];
    for (NSTextCheckingResult *match in matches) {
        if (match.resultType == NSTextCheckingTypeAddress) {
            NSDictionary *data = [match addressComponents];
            NSLog(@"address = %@, range: %@", data, NSStringFromRange(match.range));
    
            NSString *name = data[NSTextCheckingNameKey];
            if (!name && match.range.location > 0) {
                name = [str substringToIndex:match.range.location - 1];
                // "name" may now include a trailing comma and space - strip these as needed
            }
        }
    }
    

    这个输出:

    地址 = {
    城市 = 库比蒂诺;
    州 = CA;
    街道 =“222 大街”;
    },范围:{11, 30}

    奇怪的是,结果字典不包含对“星巴克”部分的引用。您可以做的是检查addressComponents 是否包含NSTextCheckingNameKey 的值。如果不是,请检查匹配范围。如果匹配的范围不是字符串的开头,那么您可以使用该值从字符串的开头提取名称。

    【讨论】:

    • 非常简洁和巧妙的方法。我不知道你可以做 NSTextCheckingTypeAddress。问题:如果 NSTextCheckingNameKey 为空,为什么我需要检查匹配的范围?
    • 看我回答中的例子。该地址不包含名称“星巴克”。由于NSTextCheckingNameKey 没有值,因此您需要查看字符串开头是否真的有名称。您可以通过查看比赛的范围来做到这一点。如果它不为零,那么您可以假设直到该匹配范围的字符串的开头是一个被忽略的名称。但这一切都取决于您需要解析的字符串。
    • 对不起,我还是一头雾水。我正在尝试从 Google 地方自动完成中删除。它以我的问题中的格式返回地址。我刚刚运行了您的代码,您是对的,“星巴克”没有参考。您能否详细说明“查看字符串开头是否真的有一个名称。您可以通过查看匹配范围来做到这一点。如果它不为零,那么您可以假设字符串的开头一直到该匹配范围是一个被忽视的名字。”在这一点上,我只是试图解析(@“星巴克,222 Main Street,Cupertino,CA”);显然星巴克是第一个字符串。
    • 能否解释一下这一行:name = [str substringToIndex:match.range.location - 1];
    • 哪部分不明白?
    【解决方案2】:

    要获取逗号之间的数组,您可以使用:

    NSArray *components = [placeResult componentsSeparatedByString:@","];
    

    可能会跟进:

    NSMutableArray *trimmedComponents =
               [NSMutableArray arrayWithCapacity:[components count]];
    
    NSCharacterSet *whitespaceCharacterSet = [NSCharacterSet whitespaceCharacterSet];
    
    for(NSString *component in components)
        [trimmedComponents addObject:
                 [component stringByTrimmingCharactersInSet:whitespaceCharacterSet]];
    

    从每个单独的组件中删除任何前导或尾随空格。您可以使用例如来反转转换

    NSString *fullAddress = [trimmedComponents componentsJoinedByString:@", "];
    

    那么问题是,给定NSString *firstComponent = [trimmedComponents objectAtIndex:0];,你如何猜测它是名字还是街道地址?如果它就像检查前面是否有一个不为零的数字那么简单,那么你可以这样做:

    if([firstComponent integerValue])
    {
        /* ... started with a non-zero number ... */
    
        NSString *trimmedAddress = [[trimmedComponents subArrayWithRange:
          NSMakeRange(1, [trimmedComponents count]-1)] componentsJoinedByString:", "];
    
        NSLog(@"trimmed address is: %@");
    }
    

    虽然条件测试也适用于placeResult,但您可能需要添加有效性检查以确保在开始假设您可以从第二个开始创建数组之前至少有两个组件。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-20
      • 2013-06-24
      • 1970-01-01
      • 1970-01-01
      • 2021-09-28
      • 1970-01-01
      相关资源
      最近更新 更多