2017-08-14 5 views
0

私のアプリでは50k +の連絡先のデータベースを持っています。リストビューでそれらを表示するには、インデックスセクションタイトルを計算して右側に表示する必要があります。連絡先の名前に基づいて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 Simulatorでテストしたところ、速くて(x10だがもっとテストはしなかった)。また、あなたのコードに小さなエラーがあります: '(contact.firstName.length> 0 && result)'と '[nameDic setObject:@" firstKey "forKey:[[contact.firstName substringToIndex:1] uppercaseString]]; 'contact.firstName'ではなく' firName'です。 – 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:)]; 

違いは何ですか


NSDictionaryの代わりに NSSetの文字を使用しました。 NSDictionaryを未使用の値で使用するのは役に立たず、キーの統一性のためだけに使います。
stringByReplacingOccurrencesOfString:withString:の代わりに stringByTrimmingCharactersInSet:を使用しました。理論的には、 stringByTrimmingCharactersInSet:のコードは、セットのものではない最初の文字で停止し、 stringByReplacingOccurrencesOfString:withString:のような文字列の最後まで続けるべきです。
characterIsMember:はRegex/Predicateよりも高速です。
•大文字のみに興味があるので、テストを実行する前に大文字に翻訳しています。後でテストする前に翻訳しておきます。

また、あなたのコードの小さな誤差:

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 
} 

それは少ないコードの重複のためだとしても、私はこれをしなかった/他

+0

あなたの努力に感謝します! –

+0

好奇心のために、あなたのソリューションが「3-6秒」かかると言っていた前に。そしていま?あなたは十分な改善を得ましたか? – Larme

+0

それは今すぐです。 200k +の連絡先は2〜3秒かかります。 –

関連する問題