Разделение NSString на NSArray, но разрешение кавычек для группировки слов - PullRequest
7 голосов
/ 25 августа 2011

У меня есть строка поиска, где люди могут использовать кавычки, чтобы сгруппировать фразы и смешать их с отдельными ключевыми словами.Например, такая строка:

"Something amazing" rooster

Я бы хотел разделить это на NSArray, чтобы он имел Something amazing (без кавычек) в качестве одного элемента и rooster в качествепрочее.

Ни componentsSeparatedByString, ни componentsSeparatedByCharactersInSet не отвечают всем требованиям.Есть ли простой способ сделать это, или я должен сам кодировать это?

Ответы [ 5 ]

2 голосов
/ 17 января 2013

Я сделал простой способ сделать это, используя 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;

}

2 голосов
/ 25 августа 2011

Вам, вероятно, придется написать часть кода самостоятельно, но сканер NSS должен стать хорошей основой для построения. Если вы используете метод scanUpToCharactersInSet, чтобы искать все, вплоть до следующего пробела или символа кавычки, чтобы можно было выбрать слова. Как только вы встретите вполне символьный символ, вы можете продолжить сканирование, используя только кавычку в наборе символов, заканчивающуюся на, чтобы пробелы в кавычках не приводили к концу токена.

1 голос
/ 11 сентября 2011

Я закончил с регулярным выражением, так как уже использовал 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 строк со строками поиска, удаляя двойные кавычки, которые окружают фразы.

1 голос
/ 25 августа 2011

Если вы позволите немного другой подход, вы можете попробовать CHCSVParser Дейва Делонга . Он предназначен для анализа строк CSV, но если вы установите пробел в качестве разделителя, я почти уверен, что вы получите намеченное поведение.

Кроме того, вы можете заглянуть в код и посмотреть, как он обрабатывает указанные поля - он опубликован под лицензией MIT.

0 голосов
/ 25 августа 2011

Я бы сначала запустил -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 из функции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...