0

我在 NSString 中有一些数据,用冒号分隔:

@"John:Doe:1970:Male:Dodge:Durango"

我需要将此字符串的总长度限制为 100 个字符。但我还需要确保存在正确数量的冒号。

截断字符串但还要添加额外的冒号以便我可以将其解析为另一侧正确数量的字段的合理方法是什么?

例如,如果我的限制是 18,你最终会得到这样的结果:

@"John:Doe:1970:Ma::"

这是我自己的最新通行证的更新版本。使用@blinkenlights 算法:

+ (NSUInteger)occurrencesOfSubstring:(NSString *)substring inString:(NSString *)string {
    // http://stackoverflow.com/a/5310084/878969
    return [string length] - [[string stringByReplacingOccurrencesOfString:substring withString:@""] length] / [substring length];
}

+ (NSString *)truncateString:(NSString *)string toLength:(NSUInteger)length butKeepDelmiter:(NSString *)delimiter {
    if (string.length <= length)
        return string;
    NSAssert(delimiter.length == 1, @"Expected delimiter to be a string containing a single character");
    int numDelimitersInOriginal = [[self class] occurrencesOfSubstring:delimiter inString:string];

    NSMutableString *truncatedString = [[string substringToIndex:length] mutableCopy];
    int numDelimitersInTruncated = [[self class] occurrencesOfSubstring:delimiter inString:truncatedString];
    int numDelimitersToAdd = numDelimitersInOriginal - numDelimitersInTruncated;
    int index = length - 1;
    while (numDelimitersToAdd > 0) { // edge case not handled here
        NSRange nextRange = NSMakeRange(index, 1);
        index -= 1;
        NSString *rangeSubstring = [truncatedString substringWithRange:nextRange];
        if ([rangeSubstring isEqualToString:delimiter])
            continue;
        [truncatedString replaceCharactersInRange:nextRange withString:delimiter];
        numDelimitersToAdd -= 1;
    }
    return truncatedString;
}

请注意,我认为此解决方案无法处理 CRD 中分隔符数量小于限制的边缘情况。

我需要正确数量的冒号的原因是服务器上的代码将拆分为冒号并期望得到 5 个字符串。

您可以假设冒号分隔字符串的组件本身不包含冒号。

4

2 回答 2

3

Your current algorithm will not produce the correct result when one or more of the characters among the last colonsToAdd is a colon.

You can use this approach instead:

  • Cut the string at 100 characters, and store the characters in an NSMutableString
  • Count the number of colons, and subtract that number from the number that you need
  • Starting at the back of the string, replace non-colon characters with colons until you have the right number of colons.
于 2013-11-13T19:26:31.193 回答
2

我倾向于@dasblinkenlight,毕竟它只是一种算法,但这里有一些代码。很少有现代速记 - 使用旧的编译器。ARC假设。不会声称它高效或美观,但它确实可以工作并处理边缘情况(重复冒号,限制字段太多):

- (NSString *)abbreviate:(NSString *)input limit:(NSUInteger)limit
{
    NSMutableArray *fields = [[input componentsSeparatedByString:@":"] mutableCopy];
    NSUInteger colonCount = fields.count - 1;

    if (colonCount >= limit)
        return [@"" stringByPaddingToLength:limit withString:@":" startingAtIndex:0];

    NSUInteger nonColonsRemaining = limit - colonCount;
    for (NSUInteger ix = 0; ix <= colonCount; ix++)
    {
        if (nonColonsRemaining > 0)
        {
            NSString *fieldValue = [fields objectAtIndex:ix];
            NSUInteger fieldLength = fieldValue.length;
            if (fieldLength <= nonColonsRemaining)
                nonColonsRemaining -= fieldLength;
            else
            {
                [fields replaceObjectAtIndex:ix withObject:[fieldValue substringToIndex:nonColonsRemaining]];
                nonColonsRemaining = 0;
            }
        }
        else
            [fields replaceObjectAtIndex:ix withObject:@""];
    }

    return [fields componentsJoinedByString:@":"];  
}
于 2013-11-13T22:20:50.020 回答