inquery
Version:
A portable indexing and searching library.
101 lines (68 loc) • 2.66 kB
JavaScript
module.exports = ( function () {
const self = {};
self.findMatch = function ( a, b ) {
const longest = a.length > b.length ? a : b;
const shortest = longest === a ? b : a;
let shortestIndex = 0;
let errorsSoFar = 0;
const errorsAllowed = 2;
let lastError = null;
for ( let i = 0; i < longest.length; i++ ) { // eslint-disable-line
const lettersMatch = ( longest[i] === shortest[shortestIndex] );
// if these letters match, check the next set of letters
if ( lettersMatch ) {
shortestIndex++; // eslint-disable-line
// unless of course, that was the last letter, in which
// case, we found a match!
if ( shortestIndex === shortest.length ) {
return i - ( shortest.length - 1 );
}
}
// if they don't match
else {
// it's okay if we're still looking for
// the start of the string
if ( shortestIndex === 0 ) {
// unless of course, the remainder of the long string is
// shorter than the short string
if ( longest.length - i < shortest.length ) {
return -1; // in that case, we know this isn't a match
}
continue; // eslint-disable-line
}
// if we're mid-string, record the error
errorsSoFar++; // eslint-disable-line
// check if this and the last letter were flipped around
// like this: something -> somtehing
const twoLettersFlippedAround = ( shortest[shortestIndex] === longest[i - 1] && shortest[shortestIndex - 1] === longest[i] ); // eslint-disable-line
// if that's too many errors or it's a consecutive error that
// wasn't caused by two letters being switched around
if ( errorsSoFar > errorsAllowed || ( lastError === ( i - 1 ) && !twoLettersFlippedAround ) ) { // eslint-disable-line
// restart looking for the beginning of the short string
// within the long string from this point
shortestIndex = 0;
errorsSoFar = 0;
// unless of course, the remainder of the long string is
// shorter than the short string
if ( longest.length - i < shortest.length ) {
return -1; // in that case, we know this isn't a match
}
continue; // eslint-disable-line
}
// if that wasn't too many errors, just move on
// to the next letter, but record when our last
// error was
shortestIndex++; // eslint-disable-line
lastError = i;
// unless that was the last letter in which case,
// that's a motherfucking match, cudi dude
if ( shortestIndex === shortest.length ) {
return i - ( shortest.length - 1 );
}
}
}
// if we made it here somehow, it's not a match
return -1;
};
return self;
}() );