Создать NSString, повторяя другую строку заданное количество раз

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

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

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

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

Есть намеки?


РЕДАКТИРОВАТЬ:

Я собирался опубликовать решение, похожее на ответ Майка МакМастера, после просмотра этой реализации из 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 Framework от Omni Group.

5 ответов

Решение

Есть метод, который называется stringByPaddingToLength:withString:startingAtIndex::

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

Обратите внимание, что если вы хотите 3 abc, чем использовать 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
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"

Для производительности вы можете зайти в 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. Там, вероятно, есть некоторые проверки, которые должны быть добавлены туда, но это прямая суть этого.

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

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

Если вы используете Какао в Python, то вы можете просто сделать это, как PyObjC наполняет NSString со всем питоном 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: решение.

[Редактировать: Заимствованная идея для использования …WithCapacity: методы из ответа Майка МакМастера.]

Другие вопросы по тегам