2011-08-25 4 views
7

Ho una stringa di ricerca, in cui le persone possono utilizzare le virgolette per raggruppare le frasi insieme e mescolare questo con le singole parole chiave. Ad esempio, una stringa come questa:Separazione NSString in NSArray, ma consentendo virgolette per raggruppare le parole

"Something amazing" rooster 

mi piacerebbe separare che in un NSArray, in modo che avrebbe Something amazing (senza virgolette) come un elemento, e rooster come l'altro.

componentsSeparatedByStringcomponentsSeparatedByCharactersInSet sembrano corrispondere al conto. C'è un modo semplice per farlo, o dovrei semplicemente farlo da solo?

+0

Si potrebbe avere un po 'di fortuna con NSRegularExpression, anche se fino a venire con un rego affidabile l'espressione lar per questo compito potrebbe essere impossibile. :-) Un altro approccio potrebbe essere solo dividere lo spazio (@ ""), quindi esaminare ogni parola alla ricerca di parole che iniziano o terminano con una citazione e combinandole in una singola frase. –

risposta

1

Ho finito con un'espressione regolare poiché stavo già utilizzando RegexKitLite e creando questa categoria 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 

Ciò restituisce un NSArray di stringhe con le stringhe di ricerca, rimuovere le virgolette che circondano le frasi.

+0

Grazie, Tim. Semplice e funziona come un fascino. È necessario eliminare l'argomento "autorelease" per le nuove versioni di iOS, ma è davvero interessante. Ed è _way_ più utile della risposta "DIY" dell'altro Tim :) – mgarciaisaia

2

Probabilmente dovrete codificare un po 'di questo da soli, ma il NSScanner dovrebbe essere una buona base su cui costruire. Se si utilizza il metodo scanUpToCharactersInSet per cercare tutto fino al successivo spazio o virgolette, è possibile selezionare parole. Una volta che si incontra un personaggio abbastanza, si può continuare a scansionare usando solo la citazione nel set di caratteri per terminare, in modo che gli spazi all'interno delle virgolette non risultino alla fine di un token.

+0

Se si sente triste con questa risposta, vedere la risposta dell'OP [qui] (http://stackoverflow.com/a/7379286/641451) con una soluzione funzionante. – mgarciaisaia

0

vorrei correre -componentsSeparatedByString:@"\"" prima, quindi creare un BOOL isPartOfQuote, inizializzato su SI se il primo carattere della stringa è stata una", ma per il resto impostato su NO

quindi creare un array di mutabile per tornare:. NSMutableArray* masterArray = [[NSMutableArray alloc] init];

Quindi, creare un ciclo sopra la matrice restituita dalla separazione.

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

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

poi tornare masterArray dalla funzione

1

Se si consente un approccio leggermente diverso, è possibile provare Dave DeLong's CHCSVParser. È inteso per analizzare le stringhe CSV, ma se si imposta il carattere dello spazio come delimitatore, sono abbastanza sicuro che si otterrà il comportamento previsto.

In alternativa, è possibile dare un'occhiata al codice e vedere come gestisce i campi citati - è pubblicato sotto la licenza MIT.

+3

+1 per ovvi motivi –

+0

@DaveDeLong, mi ci è voluto un po 'di tempo per trovare la "ragione ovvia": P –

1

Ho fatto un modo semplice per farlo usando 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; 

}

Questo metodo permette di convertire l'array in una stringa di tag, ri-citando il 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; 

}