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
sandblast
You 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 ...
Get Perl Cookbook now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.