2017-08-14 90 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秒。 –

相關問題