根据联系人姓名获取sectionIndex标题

时间:2017-08-14 13:38:21

标签: ios nsarray nsdictionary nspredicate

在我的应用程序中,我有一个50k +联系人的数据库。要在列表视图上显示它们,我需要计算索引部分标题以在右侧显示它们。

然而,我的逻辑是花费大约3-6秒的时间来准备数据源。

-(NSArray *)getSectionTitleBasedOn:(NSString*)sortBy{

    for (RealmContact *contact in contactSource){

        if (contact.firstName.length>0) {
            if ([sortBy isEqualToString:@"FirstName"]) {

                NSString *firName= [contact.firstName stringByReplacingOccurrencesOfString:@" " withString:@""];
                NSString *regex = @"^[A-Za-z]+";
                NSPredicate *test = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
                BOOL result = [test evaluateWithObject:firName];

                if (contact.firstName.length>0 && result)
                {
                    [nameDic setObject:@"firstletter" forKey:[[contact.firstName substringToIndex:1]uppercaseString]];
                }else{
                     [nameDic setObject:@"firstletter" forKey:@"#"];
                }
            }
            if ([sortBy isEqualToString:@"LastName"]) {
                //same
            }
            if ([sortBy isEqualToString:@"Company"]) {
                //same
            }

        }
    }
    NSLog(@"dic %@",nameDic);
    return [[nameDic allKeys]sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
}

我想知道我能做些什么来改善这一点。

 NSString *firName= [contact.firstName stringByReplacingOccurrencesOfString:@" " withString:@""];
 NSString *regex = @"^[A-Za-z]+";
  NSPredicate *test = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
  BOOL result = [test evaluateWithObject:firName];

我这样做是为了检查字符串是否包含特殊字符或无效字符。

获取数组后,我对其进行排序并返回数组。输出将是:

dic {
    "#" = firstletter;
    A = firstletter;
    B = firstletter;
    C = firstletter;
    D = firstletter;
    E = firstletter;
    F = firstletter;
    G = firstletter;
    H = firstletter;
    I = firstletter;
    J = firstletter;
    K = firstletter;
    L = firstletter;
    M = firstletter;
    N = firstletter;
    O = firstletter;
    P = firstletter;
    Q = firstletter;
    R = firstletter;
    S = firstletter;
    T = firstletter;
    U = firstletter;
    V = firstletter;
    W = firstletter;
    X = firstletter;
    Y = firstletter;
    Z = firstletter;
}

1 个答案:

答案 0 :(得分:1)

我这样做了:

NSArray *sortedLetters = nil;
NSMutableSet *set = [[NSMutableSet alloc] init];
NSCharacterSet *charSet = [NSCharacterSet characterSetWithCharactersInString:@"AZERTYUIOPQSDFGHJKLMWXCVBN"];
for (RealmContact *contact in _dataSource)
{
    NSString *firName = [[contact firstName] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
    if ([firName length])
    {
        unichar c = [[firName uppercaseString] characterAtIndex:0];
        if ([charSet characterIsMember:c])
        {
            [set addObject:[NSString stringWithFormat: @"%C", c]];
        }
        else
        {
            [set addObject:@"#"];
        }
    }
}
sortedLetters = [[set allObjects] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];

有什么区别?
•我使用NSSet而不是NSDictionary来表示首字母的单一性。我发现无用的NSDictionary使用未使用的值,只是为了键的唯一性 •我使用stringByTrimmingCharactersInSet:代替stringByReplacingOccurrencesOfString:withString:。从理论上讲,stringByTrimmingCharactersInSet:的代码应该停在第一个不属于集合的字符处,而不是像stringByReplacingOccurrencesOfString:withString:那样继续到字符串结尾。
•我猜characterIsMember:比正则表达式/谓词更快 •由于您只对大写感兴趣,因此我在进行测试之前对其进行了翻译,而不是之后,这也可以加速您的谓词。

此外,代码上的小错误:

if (contact.firstName.length>0 && result) 

[nameDic setObject:@"firstletter" forKey:[[contact.firstName substringToIndex:1]uppercaseString]]; 

应使用firName代替contact.firstName

this test sample上,我的解决方案似乎比你的更快(x10)。 我在OS X App(不是iOS)上快速测试。我没有做过很多测试,但值得一试。

我不知道它是否只针对这个问题,但是,你可以做的代码优化:

NSString *stringToTest = nil;
if ([sortBy isEqualToString:@"FirstName"]) 
{
    stringToTest = contact.firstName;
}
else if ([sortBy isEqualToString:@"LastName"]) 
{
    stringToTest = contact.lastName;
}
else if ([sortBy isEqualToString:@"Company"]) 
{
    stringToTest = contact.companyName;
}
stringToTest = [stringToTest stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];    
if ([stringToTest length])
{
    //Do the code with stringToTest
}

这是为了减少代码重复,也使用if / else