objective-ciossqlitensarrayfast-enumeration

improve fast enumeration performance


I have a huge word list of over 280.000+ words that is loaded from an sqlite database to an NSArray. then I do a fast enumeration to check if a certain string value entered by the user matches one of the words in the Array. Since the array is so large it takes about 1-2 seconds on the iphone 4 to go through that array.

How can I improve the performance? Maybe I should make several smaller arrays? one for each letter in the alphabet so that there is less data to go through.

this is how my database class looks

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;

}

then in my main view I initialise it like this

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

and finally I go through the array using this method

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

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

Solution

  • Lots of different ways.