【问题标题】:Get the first actual letter/number of a title获取标题的第一个实际字母/数字
【发布时间】:2013-10-15 22:21:12
【问题描述】:

我正在尝试获取标题的第一个字母/数字,它是对象的 NSString 属性。该属性有时可能为 nil 或 = @"",因此我需要对此进行补偿。如果 标题以我需要返回的数字开头@“#”。如果它以“The Cup”开头,我需要返回“C”而忽略“The”。如果它是空的,我需要为 Unknown 返回 U。

我已经创建了以下脚本,但是在搜索 1000 个标题时它非常慢。有时我也会收到-[__NSCFString substringToIndex:]: Index 1 out of bounds; string length 0。我认为这与空字符串有关?任何其他方法,如正则表达式或我可以用来加快查询速度的方法?

- (NSString *)firstLetterInTitle{
        NSString *newString = [self.title uppercaseString];
        NSNumberFormatter *f = [[NSNumberFormatter alloc] init];
            if([newString length] >= 1){
                if([f numberFromString:[newString substringToIndex:1]] != nil){
                    //All Numbers
                    _firstLetterInTitle = @"#";
                    return _firstLetterInTitle;
                }

                //" Hello"
                if([newString length] >= 2){
                    if([[newString substringToIndex:1] isEqualToString:@" "]){
                        newString = [newString stringByTrimmingCharactersInSet:
                             [NSCharacterSet whitespaceCharacterSet]];
                //Returns "Hello"
                    }
                }

        if([newString length] >= 5){
            if([[newString substringToIndex:4] isEqualToString:@"THE "]){
                newString = [newString substringFromIndex:4];
            }
        }

    }else{
        _firstLetterInTitle = @"U";
        return _firstLetterInTitle;
    }

    newString = [[newString componentsSeparatedByCharactersInSet:[[NSCharacterSet letterCharacterSet] invertedSet]] componentsJoinedByString:@""];
    if([newString length] >= 1){
        _firstLetterInTitle = [newString substringToIndex:1];
    }else{
        _firstLetterInTitle = @"U";
    }
        return _firstLetterInTitle;
}

【问题讨论】:

  • 仅供参考 - 正则表达式很少,如果有的话,让事情变得更快。
  • 谢谢你以后我会迷路
  • 为什么空值使用“U”部分标题?将空值与实际上以“U”开头的值混合在一起不是很混乱吗?
  • @rmaddy 表示未知标题。当我将它们放在表格中时,它会将空值更改为 @"Unknown Title"

标签: ios objective-c regex cocoa-touch nsstring


【解决方案1】:

这应该会快一些

- (NSString *)firstLetterInTitle
{
    if (!self.title || ([self.title isEqualToString:@""])) {
        return @"U";
    }

    if ([[NSCharacterSet decimalDigitCharacterSet] characterIsMember:[self.title characterAtIndex:0]]) {
        return @"#";
    }

    NSString *newString = [self.title uppercaseString];
    if (([newString hasPrefix:@"THE "]) && ([newString length > 4)) {
        newString = [newString substringFromIndex:4];
    }

    return [newString substringToIndex:1];
}

【讨论】:

  • +1 用于整理混乱。在问题中的第二个if 之后,我的眼睛开始流血。
  • 第二个if 不会编译。另外,if ([[NSCharacterSet decimalDigitCharacterSet] characterIsMember:[self.title characterAtIndex:0]]) 会更快。使用rangeOfCharacterFromSet: 将扫描整个字符串。您只想检查第一个字符。
  • 第三个if 应该检查第一个的长度,然后检查前缀。否则,您不必要地对短字符串进行字符串比较。
  • 第一个 if 可以缩短为if (self.title.length == 0)
  • 实际上,我认为您可能应该在第 3 个 if 上首先检查前缀。实际上,标题几乎总是 > 4,并且通常没有 THE 作为前缀,因此在大多数情况下,长度是不必要的检查,仅在存在前缀的异常情况下才需要。您需要查看数据集才能确定,但​​有根据的猜测说长度几乎总是评估为真,而前缀主要评估为假。所以你应该把最有可能评估为假的那个放在第一位,以尽量减少评估(即使它更昂贵)
猜你喜欢
  • 2019-01-16
  • 2018-07-11
  • 2020-08-19
  • 2022-11-04
  • 1970-01-01
  • 1970-01-01
  • 2016-06-03
  • 2016-11-25
  • 2021-06-23
相关资源
最近更新 更多