Search code examples
objective-cstringcomparisonnsmutablearraylevenshtein-distance

Objective-C: Comparing array of strings to user-entered string, then returning appropriate value?


This is a question about iOS programming with Objective C.

I have an NSMutableArray of strings "csvContent", that were parsed from a CSV file that contained a pseudo-database of questions, answers, and keywords. The contents of the CSV file were as follows:

ID#, "Here is the question I am asking?", "[question, key, words]", "This is the answer to your question."

There are about 2,000 of these questions and related keywords and answers, and I have successfully parsed them into the array, line by line so that each element contains everything in the example you see above.

My question is that if I want to have a user ask a question in a UITextField and then compare the UserQuestion and find the most similar question in my array of strings and then return its answer, what would be the best way to go about doing so? I've looked through documentation about Levenshtein distance and think that that would be a good option, but don't know how to exactly implement it and have it iterate through my entire CSVContent array. I'm not looking for exact code, but an ideal answer would contain some pseudocode or methodology on how to go about this.

To summarize:

  • Array of strings, CSVContent, of appearance: [id,"question",("question keywords"),"answer"].

  • I have a UITextField where I can parse a user's entered question into a string UserQuestion.

  • I want to use a fast comparison algorithm (Levenshtein?) to compare UserQuestion to the elements inside CSVContent and find the appropriate question and related answer, then return the answer.


Solution

  • When user hits the Search button, pass textField.text to this method:

     - (int)matchingIDForString:(NSString *)userSuppliedText {
    
          NSInteger bestLevDistanceSoFar = 9999999;
          int       indexOfMatch=-1;
          // having to search the entire array each time is, of course, scary.
          for ( int j=0; j<[myMutableArray count]; j++ ) {
             NSString *candidateAnswer = [myMutableArray objectAtIndex:j];
             // if candidateAnswer is a string, just use it.  Else extract the member you want...
             NSInteger *levDistance = [self myLevensteinDistanceMethod:candidateAnswer
                                                             forstring:userSuppliedText];
             if ( levDistance < bestLevDistanceSoFar ) {
                indexOfMatch = j;
                bestLevDistanceSoFar = levDistance;
             }
          }
          return indexOfMatch;   // called should test for <0 meaning no match
     }
    

    You'll need to implement this method also:

     - (NSInteger *)myLevensteinDistanceMethod:(NSString *)string1 forString:(NSString *)string2 {
         // calculate the lev distance, and return it as an NSInteger *.
     }