2009-11-18 11 views
9

Cuál es la forma más simple, dada una cadena:¿Cómo obtener las primeras N palabras de un NSString en Objective-C?

NSString *str = @"Some really really long string is here and I just want the first 10 words, for example"; 

para dar lugar a un NSString con las primeras N (por ejemplo, 10) palabras?

EDIT: También me gustaría para asegurarse de que no falla si el str es más corta que N.

Respuesta

30

Si las palabras son separados por espacios:

NSInteger nWords = 10; 
NSRange wordRange = NSMakeRange(0, nWords); 
NSArray *firstWords = [[str componentsSeparatedByString:@" "] subarrayWithRange:wordRange]; 

si quieres Interrupción en todos los espacios en blanco:

NSCharacterSet *delimiterCharacterSet = [NSCharacterSet whitespaceAndNewlineCharacterSet]; 
NSArray *firstWords = [[str componentsSeparatedByCharactersInSet:delimiterCharacterSet] subarrayWithRange:wordRange]; 

Entonces,

NSString *result = [firstWords componentsJoinedByString:@" "]; 
+0

Me ganaste: +1. No olvide los componentesJoinedByString: dado que el OP estaba buscando un resultado de NSString :) –

+0

¿Funciona esto si la cadena solo tiene 3 palabras? ¿Qué es wordIndexes? (parece no utilizado en el primer ejemplo) – philfreo

+0

Tendría que cambiar nWords si solo hay tres palabras. Podría, por supuesto, encontrar los componentes SeparatedByString y contarlos antes de decidir sobre nWords, pero no mencionó eso como un requisito en su pregunta. –

32

Si bien el código de Barry Wark funciona bien para el inglés, no es la forma preferida de detectar saltos de palabra. Muchos idiomas, como el chino y el japonés, no separan palabras usando espacios. Y el alemán, por ejemplo, tiene muchos compuestos que son difíciles de separar correctamente.

Lo que se quiere utilizar es CFStringTokenizer:

CFStringRef string; // Get string from somewhere 
CFLocaleRef locale = CFLocaleCopyCurrent(); 

CFStringTokenizerRef tokenizer = CFStringTokenizerCreate(kCFAllocatorDefault, string, CFRangeMake(0, CFStringGetLength(string)), kCFStringTokenizerUnitWord, locale); 

CFStringTokenizerTokenType tokenType = kCFStringTokenizerTokenNone; 
unsigned tokensFound = 0, desiredTokens = 10; // or the desired number of tokens 

while(kCFStringTokenizerTokenNone != (tokenType = CFStringTokenizerAdvanceToNextToken(tokenizer)) && tokensFound < desiredTokens) { 
    CFRange tokenRange = CFStringTokenizerGetCurrentTokenRange(tokenizer); 
    CFStringRef tokenValue = CFStringCreateWithSubstring(kCFAllocatorDefault, string, tokenRange); 

    // Do something with the token 
    CFShow(tokenValue); 

    CFRelease(tokenValue); 

    ++tokensFound; 
} 

// Clean up 
CFRelease(tokenizer); 
CFRelease(locale); 
+1

Sí, bien! Debería pensar más allá de mi lugar. –

+0

¡Gracias por el buen ejemplo! – pnmn

+0

@sbooth ¿Qué pasa si mi cadena comienza con un @ ... digamos como este comentario: '@sbooth ¿cómo estás? ¿Cómo puedo usar el tokenizer para encontrar algo como ["@sbooth", "how", "are", "you"]? – Georg

7

Sobre la base de la respuesta de Barry, escribí una función por el bien de esta página (aún le da crédito en SO)

+ (NSString*)firstWords:(NSString*)theStr howMany:(NSInteger)maxWords { 

    NSArray *theWords = [theStr componentsSeparatedByString:@" "]; 
    if ([theWords count] < maxWords) { 
     maxWords = [theWords count]; 
    } 
    NSRange wordRange = NSMakeRange(0, maxWords - 1); 
    NSArray *firstWords = [theWords subarrayWithRange:wordRange];  
    return [firstWords componentsJoinedByString:@" "]; 
} 
2

Aquí es mi solución, derivada de las respuestas dadas aquí, para mi propio problema de eliminar la primera palabra de una cadena ...

NSMutableArray *words = [NSMutableArray arrayWithArray:[lowerString componentsSeparatedByString:@" "]]; 
[words removeObjectAtIndex:0]; 
return [words componentsJoinedByString:@" "]; 
Cuestiones relacionadas