2017-08-14 4 views
0

Dans mon application, j'ai un db avec 50k + contacts. Pour les afficher en affichage liste, j'ai besoin de calculer les titres des sections d'index pour les afficher sur le côté droit.Obtenir les titres de sectionIndex basés sur le nom du contact

Cependant, ma logique prend environ 3-6 secondes pour préparer la source de données. Je me demande si je peux faire quelque chose pour améliorer cela. Je fais cela pour vérifier si la chaîne contient des caractères spéciaux ou des caractères invalides.

Après avoir obtenu le tableau, je le trier et retourner le tableau. La sortie serait:

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

Je l'ai fait : https://pastebin.com/ixHsPSxh Testé sur OSX Simulator, semble plus rapide (x10, mais n'a pas fait plus de tests). Aussi, petite erreur sur votre code: 'if (contact.firstName.length> 0 && result)' et '[nameDic setObject: @" firstletter "forKey: [[contact.firstName sous-chaîneToIndex: 1] majusculeString]];' devrait utiliser 'firName' au lieu de' contact.firstName'. – Larme

Répondre

1

Je l'ai fait:

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:)]; 

Quelles sont les différences?
• J'ai utilisé un NSSet au lieu d'un NSDictionary pour l'unicité des premières lettres. Je trouve inutile d'utiliser un NSDictionary avec une valeur inutilisée et juste pour l'unicité des touches. J'ai utilisé stringByTrimmingCharactersInSet: au lieu de stringByReplacingOccurrencesOfString:withString:. En théorie, le code de stringByTrimmingCharactersInSet: doit s'arrêter au premier caractère qui n'est pas de l'ensemble, et ne pas continuer jusqu'à la fin de la chaîne comme stringByReplacingOccurrencesOfString:withString:.
• Je suppose que characterIsMember: est plus rapide qu'un Regex/Predicate.
• Puisque vous ne vous intéressez qu'aux majuscules, je les ai traduites avant de faire le test, et non après, ce qui pourrait aussi accélérer le prédicat dans votre cas.

En outre, de petites erreurs sur votre code:

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

et

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

doivent utiliser firName au lieu de contact.firstName.

Sur this test sample, ma solution semble être plus rapide que le vôtre (x10). J'ai testé rapidement sur une application OS X (pas iOS). Je n'ai pas fait beaucoup de tests, mais ça vaut le coup d'essayer.

Je ne sais pas si juste pour la question, mais l'optimisation de code que vous pourriez faire:

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 
} 

Il est pour la duplication moins de code et utiliser aussi if/else

+0

Merci pour votre effort! –

+0

Pour la curiosité, avant que vous disiez que votre solution prenait "3-6 secondes". Et maintenant? Avez-vous eu assez d'amélioration? – Larme

+0

c'est instantané maintenant. Cela prend 2-3 secondes pour 200k + contacts. –