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");
}
}
}
Remplacer NSArray avec NSSet, puis devient mot de contrôle [containsObject set: mot]. –
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. –
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. –