2017-08-14 55 views
0

在我的应用程序中,我有一个带有50k +联系人的db。要在列表视图中显示它们,我需要计算索引节标题以在右侧显示它们。根据联系人姓名获取sectionIndex标题

然而,我的逻辑花费大约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; 
} 
+0

我这样做的:https://pastebin.com/ixHsPSxh测试OSX模拟器,似乎更快(x10,但没有做更多的测试)。另外,你的代码的小错误:'if(contact.firstName.length> 0 && result)'和'[nameDic setObject:@“firstletter”forKey:[[contact.firstName substringToIndex:1] uppercaseString]];'应该使用'firName'而不是'contact.firstName'。 – Larme

回答

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应用程序(不是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语句

+0

感谢您的努力! –

+0

为了好奇,在你说你的解决方案需要“3-6秒”之前。现在?你有没有得到足够的改善? – Larme

+0

现在是即时。 200k +联系人需要2-3秒。 –

相关问题