【问题标题】:Separating NSString into NSArray, but allowing quotes to group words将 NSString 分离为 NSArray,但允许引号对单词进行分组
【发布时间】:2011-08-25 15:52:28
【问题描述】:

我有一个搜索字符串,人们可以在其中使用引号将短语组合在一起,并将其与单个关键字混合。例如这样的字符串:

"Something amazing" rooster

我想把它分成一个 NSArray,这样它就有 Something amazing(不带引号)作为一个元素,rooster 作为另一个元素。

componentsSeparatedByStringcomponentsSeparatedByCharactersInSet 似乎都不符合要求。有没有一种简单的方法可以做到这一点,还是我应该自己编写代码?

【问题讨论】:

  • 你可能对 NSRegularExpression 有一些运气,尽管为此任务想出一个可靠的正则表达式可能是不可能的。 :-) 另一种方法可能只是分割空格(@" "),然后检查每个单词,寻找以引号开头或结尾的单词并将它们组合成一个短语。

标签: objective-c cocoa nsstring


【解决方案1】:

您可能必须自己编写其中的一些代码,但 NSScanner 应该是构建的良好基础。如果您使用 scanUpToCharactersInSet 方法查找直到您的下一个空格或引号字符的所有内容,则可以选择单词。一旦遇到一个相当字符,您可以继续扫描,只使用字符集中的引号作为结尾,这样引号中的空格就不会导致标记的结尾。

【讨论】:

  • 如果对这个答案感到难过,请参阅 OP 的答案 here 并提供可行的解决方案。
【解决方案2】:

我使用 NSScanner 做了一个简单的方法:

+ (NSArray *)arrayFromTagString:(NSString *)string {

NSScanner *scanner = [NSScanner scannerWithString:string];
NSString *substring;
NSMutableArray *array = [[NSMutableArray alloc] init];

while (scanner.scanLocation < string.length) {

    // test if the first character is a quote
    unichar character = [string characterAtIndex:scanner.scanLocation];
    if (character == '"') {
        // skip the first quote and scan everything up to the next quote into a substring
        [scanner setScanLocation:(scanner.scanLocation + 1)];
        [scanner scanUpToString:@"\"" intoString:&substring];
        [scanner setScanLocation:(scanner.scanLocation + 1)];  // skip the second quote too
    }
    else {
        // scan everything up to the next space into the substring
        [scanner scanUpToString:@" " intoString:&substring];
    }
    // add the substring to the array
    [array addObject:substring];

    //if not at the end, skip the space character before continuing the loop
    if (scanner.scanLocation < string.length) [scanner setScanLocation:(scanner.scanLocation + 1)];
}
return array.copy;

}

此方法会将数组转换回标签字符串,重新引用多词标签:

+ (NSString *)tagStringFromArray:(NSArray *)array {

NSMutableString *string = [[NSMutableString alloc] init];
NSRange range;

for (NSString *substring in array) {
    if (string.length > 0) {
        [string appendString:@" "];
    }
    range = [substring rangeOfString:@" "];
    if (range.location != NSNotFound) {
        [string appendFormat:@"\"%@\"", substring];
    }
    else [string appendString:substring];
}
return string.description;

}

【讨论】:

    【解决方案3】:

    我最终选择了一个正则表达式,因为我已经在使用 RegexKitLite,并创建了这个 NSString+SearchExtensions 类别。

    .h:

    //  NSString+SearchExtensions.h
    #import <Foundation/Foundation.h>
    @interface NSString (SearchExtensions)
    -(NSArray *)searchParts;
    @end
    

    .m:

    //  NSString+SearchExtensions.m
    #import "NSString+SearchExtensions.h"
    #import "RegexKitLite.h"
    
    @implementation NSString (SearchExtensions)
    
    -(NSArray *)searchParts {
        __block NSMutableArray *items = [[NSMutableArray alloc] initWithCapacity:5];
    
        [self enumerateStringsMatchedByRegex:@"\\w+|\"[\\w\\s]*\"" usingBlock: ^(NSInteger captureCount,
           NSString * const capturedStrings[captureCount],
           const NSRange capturedRanges[captureCount],
           volatile BOOL * const stop) {
    
            NSString *result = [capturedStrings[0] stringByReplacingOccurrencesOfRegex:@"\"" withString:@""];
    
            NSLog(@"Match: '%@'", result);
            [items addObject:result];
        }];        
        return [items autorelease];
    }
    @end
    

    这将返回一个包含搜索字符串的 NSArray 字符串,删除围绕短语的双引号。

    【讨论】:

    • 谢谢,蒂姆。简单,并且像魅力一样工作。对于新的 iOS 版本,您需要删除 autorelease 东西,但这真的很酷。而且方式比其他蒂姆的“DIY”答案更有帮助:)
    【解决方案4】:

    如果您允许稍微不同的方法,您可以尝试Dave DeLong's CHCSVParser。它旨在解析 CSV 字符串,但如果您将空格字符设置为分隔符,我很确定您会得到预期的行为。

    或者,您可以查看代码并查看它如何处理引用字段 - 它是在 MIT 许可下发布的。

    【讨论】:

    • @DaveDeLong,我确实花了一点时间才找到“明显的原因”:P
    【解决方案5】:

    我会先运行 -componentsSeparatedByString:@"\"",然后创建一个 BOOL isPartOfQuote,如果字符串的第一个字符是 ",则初始化为 YES,否则设置为 NO。

    然后创建一个可变数组返回: NSMutableArray* masterArray = [[NSMutableArray alloc] init];

    然后,在从分离返回的数组上创建一个循环:

    for(NSString* substring in firstSplitArray) {
        NSArray* secondSplit;
        if (isPartOfQuote == NO) {
            secondSplit = [substring componentsSeparatedByString:@" "];
        }
        else {
            secondSplit = [NSArray arrayWithObject: substring];
        }
    
        [masterArray addObjectsFromArray: secondSplit];
        isPartOfQuote = !isPartOfQuote;
    }
    

    然后从函数中返回masterArray

    【讨论】:

      猜你喜欢
      • 2010-11-04
      • 1970-01-01
      • 1970-01-01
      • 2019-12-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-02
      相关资源
      最近更新 更多