开发者

How to remove whitespace from right end of NSString?

This removes white space from both ends of a string:

NSString *newString = [oldString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];

How do I remove white space from just the right end of a string?

UPDATE: Th开发者_JS百科e code from the accepted answer is now part of SSToolkit. Yay!


UPDATE: A quick benchmark showed that Matt's own adaption, based on Max' & mine, performs best.

@implementation NSString (TrimmingAdditions)

- (NSString *)stringByTrimmingLeadingCharactersInSet:(NSCharacterSet *)characterSet {
    NSUInteger location = 0;
    NSUInteger length = [self length];
    unichar charBuffer[length];    
    [self getCharacters:charBuffer];

    for (location; location < length; location++) {
        if (![characterSet characterIsMember:charBuffer[location]]) {
            break;
        }
    }

    return [self substringWithRange:NSMakeRange(location, length - location)];
}

- (NSString *)stringByTrimmingTrailingCharactersInSet:(NSCharacterSet *)characterSet {
    NSUInteger location = 0;
    NSUInteger length = [self length];
    unichar charBuffer[length];    
    [self getCharacters:charBuffer];

    for (length; length > 0; length--) {
        if (![characterSet characterIsMember:charBuffer[length - 1]]) {
            break;
        }
    }

    return [self substringWithRange:NSMakeRange(location, length - location)];
}

@end

and then:

NSString *trimmedString = [yourString stringByTrimmingTrailingCharactersInSet:[NSCharacterset whitespaceAndNewlineCharacterSet]];

or for leading whitespace:

NSString *trimmedString = [yourString stringByTrimmingLeadingCharactersInSet:[NSCharacterset whitespaceAndNewlineCharacterSet]];

It's implemented in an abstract fashion so you can use it with any possible NSCharacterSet, whitespaceAndNewlineCharacterSet being just one of them.

For convenience you might want to add these wrapper methods:

- (NSString *)stringByTrimmingLeadingWhitespace {
    return [self stringByTrimmingLeadingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
}

- (NSString *)stringByTrimmingTrailingWhitespace {
    return [self stringByTrimmingTrailingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
}

- (NSString *)stringByTrimmingLeadingWhitespaceAndNewline {
    return [self stringByTrimmingLeadingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
}

- (NSString *)stringByTrimmingTrailingWhitespaceAndNewline {
    return [self stringByTrimmingTrailingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
}

Edit: reverted back to initial version using charBuffer for better performance.


Building on the answers by @Regexident & @Max, I came up with the following methods:

@implementation NSString (SSToolkitAdditions)

#pragma mark Trimming Methods

- (NSString *)stringByTrimmingLeadingCharactersInSet:(NSCharacterSet *)characterSet {
    NSRange rangeOfFirstWantedCharacter = [self rangeOfCharacterFromSet:[characterSet invertedSet]];
    if (rangeOfFirstWantedCharacter.location == NSNotFound) {
        return @"";
    }
    return [self substringFromIndex:rangeOfFirstWantedCharacter.location];
}

- (NSString *)stringByTrimmingLeadingWhitespaceAndNewlineCharacters {
    return [self stringByTrimmingLeadingCharactersInSet:
            [NSCharacterSet whitespaceAndNewlineCharacterSet]];
}

- (NSString *)stringByTrimmingTrailingCharactersInSet:(NSCharacterSet *)characterSet {
    NSRange rangeOfLastWantedCharacter = [self rangeOfCharacterFromSet:[characterSet invertedSet]
                                                               options:NSBackwardsSearch];
    if (rangeOfLastWantedCharacter.location == NSNotFound) {
        return @"";
    }
    return [self substringToIndex:rangeOfLastWantedCharacter.location+1]; // non-inclusive
}

- (NSString *)stringByTrimmingTrailingWhitespaceAndNewlineCharacters {
    return [self stringByTrimmingTrailingCharactersInSet:
            [NSCharacterSet whitespaceAndNewlineCharacterSet]];
}

@end

And here are the GHUnit tests, which all pass of course:

@interface StringCategoryTest : GHTestCase
@end

@implementation StringCategoryTest

- (void)testStringByTrimmingLeadingCharactersInSet {
    NSCharacterSet *letterCharSet = [NSCharacterSet letterCharacterSet];
    GHAssertEqualObjects([@"zip90210zip" stringByTrimmingLeadingCharactersInSet:letterCharSet], @"90210zip", nil);
}

- (void)testStringByTrimmingLeadingWhitespaceAndNewlineCharacters {
    GHAssertEqualObjects([@"" stringByTrimmingLeadingWhitespaceAndNewlineCharacters], @"", nil);
    GHAssertEqualObjects([@"\n \n " stringByTrimmingLeadingWhitespaceAndNewlineCharacters], @"", nil);
    GHAssertEqualObjects([@"\n hello \n" stringByTrimmingLeadingWhitespaceAndNewlineCharacters], @"hello \n", nil);
}

- (void)testStringByTrimmingTrailingCharactersInSet {
    NSCharacterSet *letterCharSet = [NSCharacterSet letterCharacterSet];
    GHAssertEqualObjects([@"zip90210zip" stringByTrimmingTrailingCharactersInSet:letterCharSet], @"zip90210", nil);
}

- (void)testStringByTrimmingTrailingWhitespaceAndNewlineCharacters {
    GHAssertEqualObjects([@"" stringByTrimmingLeadingWhitespaceAndNewlineCharacters], @"", nil);
    GHAssertEqualObjects([@"\n \n " stringByTrimmingLeadingWhitespaceAndNewlineCharacters], @"", nil);
    GHAssertEqualObjects([@"\n hello \n" stringByTrimmingTrailingWhitespaceAndNewlineCharacters], @"\n hello", nil);
}

@end

I submitted a GitHub pull request to SSToolkit with these methods added.


NSString* str = @"hdskfh   dsakjfh akhf kasdhfk asdfkjash fkadshf1234        ";
NSRange rng = [str rangeOfCharacterFromSet: [NSCharacterSet characterSetWithCharactersInString: [str stringByReplacingOccurrencesOfString: @" " withString: @""]] options: NSBackwardsSearch];
str = [str substringToIndex: rng.location+1];


Needs a slight change to account for the case when last non-trailing character is multibyte:

- (NSString *)stringByTrimmingTrailingCharactersInSet:(NSCharacterSet *)characterSet {
    NSRange rangeOfLastWantedCharacter = [self rangeOfCharacterFromSet:[characterSet invertedSet]
                                                               options:NSBackwardsSearch];
    if (rangeOfLastWantedCharacter.location == NSNotFound) {
        return @"";
    }
    return [self substringToIndex:rangeOfLastWantedCharacter.location + rangeOfLastWantedCharacter.length]; // non-inclusive
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜