2011-05-30 8 views
5

¿Qué es una implementación simple del siguiente método de categoría NSString que devuelve el número de palabras en self, donde las palabras están separadas por cualquier cantidad de espacios consecutivos o caracteres de nueva línea? Además, la cadena tendrá menos de 140 caracteres, por lo que en este caso, prefiero simplicidad & legibilidad en el sacrificio de un poco de rendimiento.Objective-C: - [NSString wordCount]

@interface NSString (Additions) 
- (NSUInteger)wordCount; 
@end 

me encontré con las siguientes soluciones:

embargo, no hay una manera más simple?

+1

No veo cómo es posible hacer algo mejor que una búsqueda lineal aquí. Dependiendo de la implementación de scanUpToCharactersFromSet, esto podría ir mejor que O (n) en la mayoría de los casos. – tjarratt

+0

@tjarratt: Creo que OP quiere el método "más simple", no necesariamente el más rápido. –

+0

¿Qué le parece enumerar por palabra yy mediante el uso de NSStringEnumerationByWords en una enumeración de cadenas? –

Respuesta

1

Parece que el segundo enlace que brindé en mi pregunta sigue reinando no solo como el más rápido sino también, en retrospectiva, como un implementation of -[NSString wordCount] relativamente simple.

+0

La definición de una palabra no se puede personalizar con esta implementación. –

15

¿Por qué no hacer lo siguiente?

- (NSUInteger)wordCount { 
    NSCharacterSet *separators = [NSCharacterSet whitespaceAndNewlineCharacterSet]; 
    NSArray *words = [self componentsSeparatedByCharactersInSet:separators]; 

    NSIndexSet *separatorIndexes = [words indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) { 
     return [obj isEqualToString:@""]; 
    }]; 

    return [words count] - [separatorIndexes count]; 
} 
+0

¡Gracias! Eso parece exactamente correcto y simple. Me pregunto si es eficiente. Lo suficientemente bueno en mi caso, aunque estoy construyendo una aplicación de iOS, no un sistema operativo. :) ¡Me gusta! – ma11hew28

+0

Hmm ... No creo que esto sea exactamente correcto. De acuerdo con la documentación de Xcode: "Las ocurrencias adyacentes de los caracteres separadores producen cadenas vacías en el resultado. De manera similar, si la cadena comienza o termina con caracteres separadores, la primera o la última subcadena, respectivamente, está vacía". No quiero contar cadenas vacías como palabras. Por ejemplo, el método debería devolver 1 para '@" hola "', no 3. – ma11hew28

+0

¡agradable!¡Funciona! También confirmé la corrección de otra solución que encontré en la red, y parece casi el doble de rápido que su implementación y aún bastante simple. Entonces, [lo publiqué como una respuesta] (http://stackoverflow.com/questions/6171422/objective-c-nsstring-wordcount/6171849#6171849). – ma11hew28

3
- (NSUInteger) wordCount 
{ 
    NSArray *words = [self componentsSeparatedByString:@" "]; 
    return [words count]; 
} 
+1

Esto cuenta más si tienes corridas de espacios o nuevas líneas. – Obliquely

+0

Conteo incorrecto para espacios múltiples o líneas nuevas múltiples '@" \ n \ n \ n "'. Consulte la solución correcta anterior: http://stackoverflow.com/a/6171439/1033581 –

8

Hay una serie de implementaciones más simples, pero todos ellos tienen ventajas y desventajas. Por ejemplo, cacao (pero no Cocoa Touch) tiene palabra de conteo de horneado en:

- (NSUInteger)wordCount { 
    return [[NSSpellChecker sharedSpellChecker] countWordsInString:self language:nil]; 
} 

También es trivial para contar las palabras con la mayor precisión el escáner simplemente usando [[self componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] count]. Pero he encontrado que el rendimiento de ese método se degrada mucho para cadenas más largas.

Por lo tanto, depende de las compensaciones que desee realizar. He encontrado que el más rápido absoluto es simplemente ir directamente al ICU. Si lo que quiere es más simple, usar el código existente es probablemente más simple que escribir cualquier código.

8

Creo que ha identificado lo "más simple". Sin embargo, para responder a su pregunta original - "una implementación sencilla de la siguiente categoría NSString ...", y lo han publicado directamente aquí para la posteridad:

@implementation NSString (GSBString) 

- (NSUInteger)wordCount 
{ 
    __block int words = 0; 
    [self enumerateSubstringsInRange:NSMakeRange(0,self.length) 
          options:NSStringEnumerationByWords 
          usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {words++;}]; 
    return words; 
} 

@end 
+0

La definición de una palabra no se puede personalizar con esta implementación. –

+0

@ Cœur pero hay idiomas sin espacios. –

0

Swift 3:

let words: [Any] = (string.components(separatedBy: " ")) 
let count = words.count 
Cuestiones relacionadas