2012-08-15 4 views
0

J'ai une énorme liste de mots de plus de 280.000 mots qui est chargée à partir d'une base de données sqlite à un NSArray. Ensuite, je fais une énumération rapide pour vérifier si une certaine valeur de chaîne entrée par l'utilisateur correspond à l'un des mots du tableau. Depuis le tableau est si grand, il faut environ 1-2 secondes sur l'iphone 4 pour passer par ce tableau.améliorer énumération rapide performace

Comment puis-je améliorer les performances? Peut-être que je devrais faire plusieurs tableaux plus petits? un pour chaque lettre de l'alphabet afin qu'il y ait moins de données à passer.

c'est ainsi que ma classe de base de données ressemble

static WordDatabase *_database; 

+(WordDatabase *) database 
{ 

    if (_database == nil) { 

     _database = [[WordDatabase alloc] init]; 

    } 

    return _database; 
} 

- (id) init 
{ 
    if ((self = [super init])) { 
     NSString *sqLiteDb = [[NSBundle mainBundle] pathForResource:@"dictionary" ofType:@"sqlite"]; 


     if (sqlite3_open([sqLiteDb UTF8String], &_database) != SQLITE_OK) { 
      NSLog(@"Failed to open database!"); 
     } 
    } 
    return self; 

} 

- (NSArray *)dictionaryWords { 

    NSMutableArray *retval = [[[NSMutableArray alloc] init] autorelease]; 
    NSString *query = @"SELECT word FROM words"; 
    sqlite3_stmt *statement; 

    if (sqlite3_prepare_v2(_database, [query UTF8String], -1, &statement, nil) == SQLITE_OK) { 
     while (sqlite3_step(statement) == SQLITE_ROW) { 

      char *wordChars = (char *) sqlite3_column_text(statement, 0); 

      NSString *name = [[NSString alloc] initWithUTF8String:wordChars]; 

      name = [name uppercaseString]; 

      [retval addObject:name]; 

     } 
     sqlite3_finalize(statement); 
    } 

    return retval; 

} 

alors à mon avis principal que j'INITIALISER comme ça

dictionary = [[NSArray alloc] initWithArray:[WordDatabase database].dictionaryWords]; 

et enfin je vais à travers le réseau en utilisant cette méthode

- (void) checkWord 
{  
    NSString *userWord = formedWord.wordLabel.string; 
    NSLog(@"checking dictionary for %@", userWord); 

    for (NSString *word in dictionary) { 
     if ([userWord isEqualToString: word]) { 
     NSLog(@"match found");  
     }  
    } 
} 
+1

Remplacer NSArray avec NSSet, puis devient mot de contrôle [containsObject set: mot]. –

+0

en effet. changer le NSArray à un NSSet a fait le contrôle presque instantanément. bien que le chargement initial du dictionnaire soit devenu légèrement plus long. mais c'est un petit compromis. –

+0

C'est quand même beaucoup de mémoire. Si votre application a besoin de faire autre chose, vous pouvez trouver que la recherche SQL est assez bonne, surtout si vous indexez votre base de données sur les mots ... Vous pouvez même simplement utiliser la base de données SQL comme une grande table. Créer un hachage avec le mot, puis demander à la base de données pour tous les mots correspondant à ce hachage. Une recherche linéaire sur cette petite liste ne sera rien, et la recherche SQL sur une valeur entière indexée est très rapide. Alors vous n'avez pas besoin d'utiliser toute cette mémoire non plus. –

Répondre

4

Beaucoup de façons différentes.

  • coller tous les mots dans un dictionnaire ou un ensemble, test de présence est rapide

  • le casser comme vous le suggérez; créer une structure de type arbre de quelque sorte.

  • utiliser la base de données pour effectuer la recherche. Ils sont généralement très bien à cela, si construit correctement.

+2

Vous voudriez un ensemble, pas un dictionnaire, puisque les données ne semblent pas être saisies. –

+0

Assez vrai; un ensemble sera plus efficace. – bbum

0

Si l'espace n'est pas un problème, conservez une valeur de hachage de chaque mot et utilisez-la pour votre recherche de base. Une fois filtré par le hachage, comparez chacun des mots. Cela permettra de réduire le nombre de comparaisons de chaînes coûteuses. Plus facile à indexer/trier et effectue des recherches rapides.

0

Je seconde un dictionnaire. NSDictionary pour l'objectif c.

par exemple:

// Pour imprimer toutes les paires clé-valeur dans la NSDictionary mondict

for(id key in myDict) 
    NSLog(@"key=%@ value=%@", key, [myDict objectForKey:key]); 
+0

Notez que l'énumération basée sur des blocs de dictionnaires est nettement plus rapide car elle ne nécessite pas de recherche de hachage pour obtenir la valeur. – bbum

Questions connexes