2008-11-04 1 views
51

Это должно быть легко, но мне сложно найти самое легкое решение.Создайте NSString, повторив другую строку определенное количество раз

Мне нужен NSString, который равен другой строке, объединенной с собой определенное количество раз.

Для лучшего объяснения, рассмотрим следующий пример Python:

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

Любые намеки?


EDIT:

Я собирался опубликовать решение, похожее на один по Mike McMaster's answer, посмотрев на эту реализацию из 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]; 
} 

Код воспроизведенной из файла:

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

в рамке OpenExtensions от Omni Frameworks от The Omni Group.

ответ

145

Существует метод, называемый stringByPaddingToLength:withString:startingAtIndex::

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

Обратите внимание, что если вы хотите 3 азбуки, чем использовать 9 (3 * [@"abc" length]) или создать категорию, как это:

@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 
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

Я пытался придумать что-то более простое, но я думаю, что это самый короткий путь. – 2008-11-04 05:21:18

+0

Я сделал это немного более эффективным с момента принятия, указав время сначала и имея емкость = [оригинальная длина] * раз – 2008-11-04 05:21:54

+1

Просто для полноты, если по какой-то причине вы хотите использовать большие числа, вы можете улучшить это, из двух конкатенаций (например, foo * 10 = foo * 2 + foo * 8; foo * 8 = foo * 4 + foo * 4; foo * 4 = foo * 2 + foo * 2 -> 3 concat operations вместо 9) , – 2008-11-04 09:14:56

1

Если вы используете какао в Python, то вы можете просто сделать это, так как PyObjC насыщает NSString со всеми способностями класса Python unicode в.

В противном случае существует два способа.

Один из них - это создать массив с той же строкой в ​​нем n раз и использовать componentsJoinedByString:. Что-то вроде этого:

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

Другой путь был бы начать с пустой NSMutableString и добавить строку к нему n раз, как это:

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

Вы можете вырезать stringWithString: вызовите, если вам нормально возвращать здесь изменяемую строку. В противном случае вы, вероятно, должны вернуть неизменяемую строку, а сообщение stringWithString: означает, что у вас есть две копии строки в памяти.

Поэтому я рекомендую решение componentsJoinedByString:.

[Edit: Заимствованные идея использовать …WithCapacity: методы из Mike McMaster's answer.]

+0

Спасибо за альтернативу использования компонентовJoinedByString. – 2008-11-04 05:28:04

4

Для повышения производительности, вы можете зайти в C-то вроде этого:

+ (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]; 
} 

Это может быть записано как категория расширения на класс NSString. Вероятно, есть некоторые проверки, которые нужно бросить туда, но это прямолинейный смысл.

2

Первый метод, приведенный выше, предназначен для одного символа. Это для строки символов. Он также может использоваться для одного символа, но имеет больше накладных расходов.

+ (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]; 
}