将 NSString 分离成 N​​SArray,但允许用引号对单词进行分组

发布于 2024-12-01 13:06:18 字数 360 浏览 1 评论 0原文

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

"Something amazing" rooster

我想将其分离到 NSArray 中,这样它将有 Something Amazing (不带引号)作为一个元素,以及 rooster和另一个一样。

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

I have a search string, where people can use quotes to group phrases together, and mix this with individual keywords. For example, a string like this:

"Something amazing" rooster

I'd like to separate that into an NSArray, so that it would have Something amazing (without quotes) as one element, and rooster as the other.

Neither componentsSeparatedByString nor componentsSeparatedByCharactersInSet seem to fit the bill. Is there an easy way to do this, or should I just code it up myself?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

回忆躺在深渊里 2024-12-08 13:06:18

您可能需要自己编写其中的一些代码,但 NSScanner 应该是构建的良好基础。如果您使用 scanUpToCharactersInSet 方法来查找直到下一个空格或引号字符的所有内容,以便可以挑选单词。一旦遇到完全字符,您可以仅使用字符集中的引号继续扫描以结束,这样引号内的空格就不会导致标记结束。

You probably will have to code some of this up yourself, but the NSScanner should be a good basis on which to build. If you use the scanUpToCharactersInSet method to look for everything up to your next whitespace or quote character to can pick off words. Once you encounter a quite character, you could continue to scan using just the quote in the character set to end at, so that spaces within the quotes don't result in the end of a token.

睫毛溺水了 2024-12-08 13:06:18

我使用 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;

}

I made a simple way to do this using 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;

}

This method will convert the array back to a tag string, re-quoting the multi-word tags:

+ (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;

}

束缚m 2024-12-08 13:06:18

我最终使用了正则表达式,因为我已经在使用 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 字符串,删除短语周围的双引号。

I ended up going with a regular expression as I was already using RegexKitLite, and creating this NSString+SearchExtensions category.

.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

This returns an NSArray of strings with the search strings, removing the double quotes that surround the phrases.

游魂 2024-12-08 13:06:18

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

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

If you'll allow a slightly different approach, you could try Dave DeLong's CHCSVParser. It is intended to parse CSV strings, but if you set the space character as the delimiter, I am pretty sure you will get the intended behavior.

Alternatively, you can peek into the code and see how it handles quoted fields - it is published under the MIT license.

情痴 2024-12-08 13:06:18

我会首先运行 -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

I would run -componentsSeparatedByString:@"\"" first, then create a BOOL isPartOfQuote, initialized to YES if the first character of the string was a ", but otherwise set to NO.

Then create a mutable array to return:
NSMutableArray* masterArray = [[NSMutableArray alloc] init];

Then, create a loop over the array returned from the separation:

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

    [masterArray addObjectsFromArray: secondSplit];
    isPartOfQuote = !isPartOfQuote;
}

Then return masterArray from the function.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文