反转NSString文本

Sim*_*iwi 51 cocoa objective-c nsstring

我一直在谷歌搜索如何做到这一点,但我将如何扭转NSString?例如:嗨会变成:呃

我正在寻找最简单的方法来做到这一点.

谢谢!

@Vince我做了这个方法:

- (IBAction)doneKeyboard {

// first retrieve the text of textField1
NSString *myString = field1.text;
NSMutableString *reversedString = [NSMutableString string];
NSUInteger charIndex = 0;
while(myString && charIndex < [myString length]) {
    NSRange subStrRange = NSMakeRange(charIndex, 1);
    [reversedString appendString:[myString substringWithRange:subStrRange]];
    charIndex++;
}
// reversedString is reversed, or empty if myString was nil
field2.text = reversedString;
}
Run Code Online (Sandbox Code Playgroud)

我把那个方法连接到textfield1的didendonexit.当我单击完成按钮时,它不会反转文本,UILabel只显示我输入的UITextField文本.怎么了?

Jan*_*ano 103

阻止版本.

NSString *myString = @"abcdefghijklmnopqrstuvwxyz";
NSMutableString *reversedString = [NSMutableString stringWithCapacity:[myString length]];

[myString enumerateSubstringsInRange:NSMakeRange(0,[myString length]) 
                             options:(NSStringEnumerationReverse | NSStringEnumerationByComposedCharacterSequences)
                          usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
                            [reversedString appendString:substring];
                        }];

// reversedString is now zyxwvutsrqponmlkjihgfedcba
Run Code Online (Sandbox Code Playgroud)

  • 哇,到目前为止,这是唯一正确的解决方案(包括代理对和组成的字符序列). (7认同)
  • 我喜欢这一个.十分优雅. (3认同)

小智 51

写一个简单的循环来做到这一点:

// myString is "hi"
NSMutableString *reversedString = [NSMutableString string];
NSInteger charIndex = [myString length];
while (charIndex > 0) {
    charIndex--;
    NSRange subStrRange = NSMakeRange(charIndex, 1);
    [reversedString appendString:[myString substringWithRange:subStrRange]];
}
NSLog(@"%@", reversedString); // outputs "ih"
Run Code Online (Sandbox Code Playgroud)

在你的情况下:

// first retrieve the text of textField1
NSString *myString = textField1.text;
NSMutableString *reversedString = [NSMutableString string];
NSInteger charIndex = [myString length];
while (myString && charIndex > 0) {
    charIndex--;
    NSRange subStrRange = NSMakeRange(charIndex, 1);
    [reversedString appendString:[myString substringWithRange:subStrRange]];
}
// reversedString is reversed, or empty if myString was nil
textField2.text = reversedString;
Run Code Online (Sandbox Code Playgroud)

  • -1:组合字符序列或代理对中断.示例:@""或@"" (4认同)
  • 系统不允许我编辑它,但charIndex> = 0应该是charIndex> 0,因为> =允许charIndex为-1,这将崩溃. (2认同)

小智 11

jano的回答是正确的.不幸的是,它会产生许多不必要的临时对象.这是一个更快(更复杂)的实现,基本上做同样的事情,但使用memcpy和unichar缓冲区将内存分配保持在最低限度.

- (NSString *)reversedString
{
    NSUInteger length = [self length];
    if (length < 2) {
        return self;
    }

    unichar *characters = calloc(length, sizeof(unichar));
    unichar *reversedCharacters = calloc(length, sizeof(unichar));
    if (!characters || !reversedCharacters) {
        free(characters);
        free(reversedCharacters);
        return nil;
    }

    [self getCharacters:characters range:NSMakeRange(0, length)];

    NSUInteger i = length - 1;
    NSUInteger copiedCharacterCount = 0;

    // Starting from the end of self, copy each composed character sequence into reversedCharacters
    while (copiedCharacterCount < length) {
        NSRange characterRange = [self rangeOfComposedCharacterSequenceAtIndex:i];
        memcpy(reversedCharacters + copiedCharacterCount, characters + characterRange.location, characterRange.length * sizeof(unichar));
        i = characterRange.location - 1;
        copiedCharacterCount += characterRange.length;
    }

    free(characters);

    NSString *reversedString = [[NSString alloc] initWithCharactersNoCopy:reversedCharacters length:length freeWhenDone:YES];
    if (!reversedString) {
        free(reversedCharacters);
    }

    return reversedString;
}
Run Code Online (Sandbox Code Playgroud)

我在100,000个随机多字节Unicode字符串上测试了这个,长度在1到128之间.这个版本比jano快4-5倍.

Enumerate substrings: 2.890528
MemCopy: 0.671090
Enumerate substrings: 2.840411
MemCopy: 0.662882
Run Code Online (Sandbox Code Playgroud)

测试代码位于https://gist.github.com/prachigauriar/9739805.

更新:我通过简单地转换为UTF-32缓冲区并反转它再次尝试了这一点.

- (NSString *)qlc_reversedStringWithUTF32Buffer
{
    NSUInteger length = [self length];
    if (length < 2) {
        return self;
    }

    NSStringEncoding encoding = NSHostByteOrder() == NS_BigEndian ? NSUTF32BigEndianStringEncoding : NSUTF32LittleEndianStringEncoding;
    NSUInteger utf32ByteCount = [self lengthOfBytesUsingEncoding:encoding];
    uint32_t *characters = malloc(utf32ByteCount);
    if (!characters) {
        return nil;
    }

    [self getBytes:characters maxLength:utf32ByteCount usedLength:NULL encoding:encoding options:0 range:NSMakeRange(0, length) remainingRange:NULL];

    NSUInteger utf32Length = utf32ByteCount / sizeof(uint32_t);
    NSUInteger halfwayPoint = utf32Length / 2;
    for (NSUInteger i = 0; i < halfwayPoint; ++i) {
        uint32_t character = characters[utf32Length - i - 1];
        characters[utf32Length - i - 1] = characters[i];
        characters[i] = character;
    }

    return [[NSString alloc] initWithBytesNoCopy:characters length:utf32ByteCount encoding:encoding freeWhenDone:YES];
}
Run Code Online (Sandbox Code Playgroud)

这比memcpy版本快3-4倍.上述要点已使用最新版本的代码进行了更新.

Enumerate substrings: 2.168705
MemCopy: 0.488320
UTF-32: 0.150822
Enumerate substrings: 2.169655
MemCopy: 0.481786
UTF-32: 0.147534
Enumerate substrings: 2.248812
MemCopy: 0.505995
UTF-32: 0.154531
Run Code Online (Sandbox Code Playgroud)


jpa*_*500 8

我想我会抛出另一个版本以防万一有人感兴趣..个人而言,我喜欢使用NSMutableString的更清洁的方法,但如果性能是最高优先级,那么这个更快:

- (NSString *)reverseString:(NSString *)input {
    NSUInteger len = [input length];
    unichar *buffer = malloc(len * sizeof(unichar));
    if (buffer == nil) return nil; // error!
    [input getCharacters:buffer];

    // reverse string; only need to loop through first half
    for (NSUInteger stPos=0, endPos=len-1; stPos < len/2; stPos++, endPos--) {
        unichar temp = buffer[stPos];
        buffer[stPos] = buffer[endPos];
        buffer[endPos] = temp;
    }

    return [[NSString alloc] initWithCharactersNoCopy:buffer length:len freeWhenDone:YES];
}
Run Code Online (Sandbox Code Playgroud)

我还写了一个快速测试,以便将它与更传统的NSMutableString方法(我在下面也包括在内)进行比较:

// test reversing a really large string
NSMutableString *string = [NSMutableString new];
for (int i = 0; i < 10000000; i++) {
    int digit = i % 10;
    [string appendFormat:@"%d", digit];
}
NSTimeInterval startTime = [[NSDate date] timeIntervalSince1970];
NSString *reverse = [self reverseString:string];
NSTimeInterval elapsedTime = [[NSDate date] timeIntervalSince1970] - startTime;
NSLog(@"reversed in %f secs", elapsedTime);
Run Code Online (Sandbox Code Playgroud)

结果是:

  • 使用NSMutableString方法(下) - "在3.720631秒内反转"

  • 使用unichar*缓冲方法(上图) - "在0.032604秒内反转"

仅供参考,这是用于此比较的NSMutableString方法:

- (NSString *)reverseString:(NSString *)input {
    NSUInteger len = [input length];
    NSMutableString *result = [[NSMutableString alloc] initWithCapacity:len];
    for (int i = len - 1; i >= 0; i--) {
        [result appendFormat:@"%c", [input characterAtIndex:i]];
    }
    return result;
}
Run Code Online (Sandbox Code Playgroud)