截断分隔的NSString而不删除分隔符

时间:2013-11-13 19:16:01

标签: ios objective-c regex string

我在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个字符串。

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

2 个答案:

答案 0 :(得分:3)

当最后一个colonsToAdd中的一个或多个字符是冒号时,您当前的算法将无法产生正确的结果。

您可以改用此方法:

  • 将字符串剪切为100个字符,并将字符存储在NSMutableString
  • 计算冒号数量,并从您需要的数字中减去该数字
  • 从字符串后面开始,用冒号替换非冒号字符,直到你有正确数量的冒号。

答案 1 :(得分: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:@":"];  
}
相关问题