Approximate Matching
Problem
You want to match something fuzzily.
Any time you want to be forgiving of misspellings in user input, you want to do fuzzy matching.
Solution
Use the String::Approx module, available from CPAN:
use String::Approx qw(amatch);
if (amatch("PATTERN", @list)) {
# matched
}
@matches = amatch("PATTERN", @list);Discussion
String::Approx calculates the difference
between the pattern and each string in the list. If less than a
certain number (by default, 10 percent of the length of the pattern)
one-character insertions, deletions, or substitutions are required to
make the string from the pattern, the string “matches”
the pattern. In scalar context, amatch returns the
number of successful matches. In list context, it returns those
strings that matched.
use String::Approx qw(amatch);
open(DICT, "/usr/dict/words") or die "Can't open dict: $!";
while(<DICT>) {
print if amatch("balast");
}
ballast
balustrade
blast
blastula
sandblastYou can also pass options to amatch to control
case-insensitivity and the number of insertions, deletions, or
substitutions to have. These options are passed in as a list
reference; they’re fully described in the String::Approx
documentation.
It must be noted that using the module’s matching function seems to run between 10 and 40 times slower than Perl’s built-in matching function. Only use String::Approx if you’re after fuzziness in your matching that Perl’s regular expressions can’t provide.
See Also
The documentation for the CPAN ...