2008-11-04 16 views
51

Esto debería ser fácil, pero estoy teniendo dificultades para encontrar la solución más fácil.Crear NSString repitiendo otra cadena un número determinado de veces

Necesito un NSString que es igual a otra cadena concatenada consigo mismo un determinado número de veces.

Para una mejor explicación, considere el siguiente ejemplo pitón:

>> original = "abc" 
"abc" 
>> times = 2 
2 
>> result = original * times 
"abcabc" 

¿Alguna pista?


EDIT:

que iba a publicar una solución similar a la que por Mike McMaster's answer, después de mirar esta implementación de los OmniFrameworks:

// returns a string consisting of 'aLenght' spaces 
+ (NSString *)spacesOfLength:(unsigned int)aLength; 
{ 
static NSMutableString *spaces = nil; 
static NSLock *spacesLock; 
static unsigned int spacesLength; 

if (!spaces) { 
spaces = [@"    " mutableCopy]; 
spacesLength = [spaces length]; 
    spacesLock = [[NSLock alloc] init]; 
} 
if (spacesLength < aLength) { 
    [spacesLock lock]; 
    while (spacesLength < aLength) { 
     [spaces appendString:spaces]; 
     spacesLength += spacesLength; 
    } 
    [spacesLock unlock]; 
} 
return [spaces substringToIndex:aLength]; 
} 

Código reproducida a partir del archivo:

Frameworks/OmniFoundation/OpenStepExtensions.subproj/NSString-OFExtensions.m 

en el marco OpenExtensions del Omni Frameworks por The Omni Group.

Respuesta

145

Hay un método llamado stringByPaddingToLength:withString:startingAtIndex::

[@"" stringByPaddingToLength:100 withString: @"abc" startingAtIndex:0] 

Tenga en cuenta que si quieres 3 de abc, de usar 9 (3 * [@"abc" length]) o crear la categoría de esta manera:

@interface NSString (Repeat) 

- (NSString *)repeatTimes:(NSUInteger)times; 

@end 

@implementation NSString (Repeat) 

- (NSString *)repeatTimes:(NSUInteger)times { 
    return [@"" stringByPaddingToLength:times * [self length] withString:self startingAtIndex:0]; 
} 

@end 
+3

+1 para hacerlo todo en una sola llamada a la biblioteca estándar. Y así es como lo usé para crear una lista de signos de interrogación separados por comas (para alimentar a SQLite) - '[@" "stringByPaddingToLength: [fields count] * 2-1 withString: @"? "StartingAtIndex: 0] '. – noamtm

7
NSString *original = @"abc"; 
int times = 2; 

// Capacity does not limit the length, it's just an initial capacity 
NSMutableString *result = [NSMutableString stringWithCapacity:[original length] * times]; 

int i; 
for (i = 0; i < times; i++) 
    [result appendString:original]; 

NSLog(@"result: %@", result); // prints "abcabc" 
+0

yo estaba tratando para llegar a algo más simple, pero creo que este es el camino más corto. –

+0

Lo hice un poco más eficiente desde la aceptación especificando primero los tiempos y teniendo la capacidad = [longitud original] * veces –

+1

Solo para completar, si por alguna razón quiere usar números grandes, puede mejorar esto reutilizando energía- de-dos concatenaciones (por ejemplo, foo * 10 = foo * 2 + foo * 8; foo * 8 = foo * 4 + foo * 4; foo * 4 = foo * 2 + foo * 2 -> 3 operaciones concat en lugar de 9) . –

1

Si utiliza cacao en Python, a continuación, sólo puede hacer eso, como PyObjC impregna NSString con todas las habilidades de la clase Python unicode.

De lo contrario, hay dos maneras.

Una es crear una matriz con la misma cadena en ella n veces, y usar componentsJoinedByString:. Algo como esto:

NSMutableArray *repetitions = [NSMutableArray arrayWithCapacity:n]; 
for (NSUInteger i = 0UL; i < n; ++i) 
    [repetitions addObject:inputString]; 
outputString = [repetitions componentsJoinedByString:@""]; 

La otra forma sería comenzar con un vacío NSMutableString y anexar la cadena para que n veces, como este:

NSMutableString *temp = [NSMutableString stringWithCapacity:[inputString length] * n]; 
for (NSUInteger i = 0UL; i < n; ++i) 
    [temp appendString:inputString]; 
outputString = [NSString stringWithString:temp]; 

Usted puede ser capaz de cortar el stringWithString: llame si está bien que devuelva una cadena mutable aquí. De lo contrario, probablemente deba devolver una cadena inmutable, y el mensaje stringWithString: aquí significa que tiene dos copias de la cadena en la memoria.

Por lo tanto, recomiendo la solución componentsJoinedByString:.

[Editar: Borrowed idea de utilizar …WithCapacity: métodos de Mike McMaster's answer.]

+0

Gracias por la alternativa de usar componentsJoinedByString. –

+0

Sí, buena sugerencia. Probablemente un poco más eficiente que mi solución (reconocidamente genérica). –

4

Para obtener un rendimiento, que podría caer en C con algo como esto:

+ (NSString*)stringWithRepeatCharacter:(char)character times:(unsigned int)repetitions; 
{ 
    char repeatString[repetitions + 1]; 
    memset(repeatString, character, repetitions); 

    // Set terminating null 
    repeatString[repetitions] = 0; 

    return [NSString stringWithCString:repeatString]; 
} 

Esto podría ser escrito como una extensión de la categoría de la clase NSString. Probablemente haya algunos controles que deberían arrojarse allí, pero esta es la esencia de esto.

+0

Una gran idea, especialmente para escenarios hambrientos de rendimiento. ¡Gracias! –

+0

compruebe si las repeticiones> 0? –

+0

David, las repeticiones son unsigned int – jessecurry

2

El primer método anterior es para un solo carácter. Este es para una cadena de caracteres. Se podría usar también para un solo personaje pero tiene más sobrecarga.

+ (NSString*)stringWithRepeatString:(char*)characters times:(unsigned int)repetitions; 
{ 
    unsigned int stringLength = strlen(characters); 
    unsigned int repeatStringLength = stringLength * repetitions + 1; 

    char repeatString[repeatStringLength]; 

    for (unsigned int i = 0; i < repetitions; i++) { 
     unsigned int pointerPosition = i * repetitions; 
     memcpy(repeatString + pointerPosition, characters, stringLength);  
    } 

    // Set terminating null 
    repeatString[repeatStringLength - 1] = 0; 

    return [NSString stringWithCString:repeatString]; 
} 
+0

hay un error, creo que, dentro del ciclo de: 'unsigned int pointerPosition = i * repeticiones;' debe ser 'unsigned int pointerPosition = i * StringLength;' donde ** ** I * repeticiones convierte ** i * stringLength **. – mginius

Cuestiones relacionadas