Создайте 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 Frameworks от Группа Омни.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
58
0
25 448
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

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"

Я пытался придумать что-то попроще, но думаю, что это самый короткий путь.

Sergio Acosta 04.11.2008 08:21

Я сделал его немного более эффективным с момента принятия, указав сначала время и указав емкость = [исходная длина] * раз

Mike McMaster 04.11.2008 08:21

Для полноты картины, если по какой-то причине вы хотите использовать большие числа, вы можете улучшить это, повторно используя конкатенации степени двойки (например, foo * 10 = foo * 2 + foo * 8; foo * 8 = foo * 4 + foo * 4; foo * 4 = foo * 2 + foo * 2 -> 3 операции concat вместо 9).

Jens Ayton 04.11.2008 12:14

Это решение не так эффективно, как верхний ответ с использованием stringByPaddingToLength:withString:startingAtIndex:

Cœur 27.06.2016 09:43

Если вы используете Cocoa в 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: из Ответ Майка Макмастера.]

Спасибо за альтернативу использованию componentsJoinedByString.

Sergio Acosta 04.11.2008 08:28

Да, хорошее предложение. Вероятно, немного более эффективно, чем мое (по общему признанию общее) решение.

Mike McMaster 04.11.2008 08:39

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

Отличная идея, особенно для сценариев, требующих высокой производительности. Спасибо!

Sergio Acosta 27.07.2009 12:20

Дэвид, повторения - это беззнаковое целое число

jessecurry 08.07.2010 00:31

Я не удивлюсь, если окажется, что NSStringstringByPaddingToLength:withString:startingAtIndex: реализован таким же образом.

ArtOfWarfare 02.09.2013 22:58

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

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

Я думаю, что есть ошибка внутри цикла for: unsigned int pointerPosition = i * repetitions; должен быть unsigned int pointerPosition = i * stringLength;, где я * повторения становится я * stringLength.

mginius 11.05.2016 20:14
Ответ принят как подходящий

Есть метод под названием 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

+1 за то, что все это делается за один вызов стандартной библиотеки. И вот как я использовал его для создания списка вопросительных знаков, разделенных запятыми (для передачи в SQLite) - [@"" stringByPaddingToLength:[fields count]*2-1 withString:@"?," startingAtIndex:0].

noamtm 07.08.2012 22:00

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