Move FuzzyMap core functionality to FuzzyMapTools for reuse
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package kiss;
|
||||
|
||||
import haxe.ds.StringMap;
|
||||
import kiss.FuzzyMapTools;
|
||||
|
||||
using hx.strings.Strings;
|
||||
|
||||
@@ -20,37 +21,8 @@ abstract FuzzyMap<T>(StringMap<T>) from StringMap<T> to StringMap<T> {
|
||||
return this;
|
||||
}
|
||||
|
||||
static var threshold = 0.4;
|
||||
public static function fuzzyMatchScore(key:String, fuzzySearchKey:String) {
|
||||
return 1 - (key.toLowerCase().getLevenshteinDistance(fuzzySearchKey.toLowerCase()) / Math.max(key.length, fuzzySearchKey.length));
|
||||
}
|
||||
|
||||
function bestMatch(fuzzySearchKey:String, ?throwIfNone=true):String {
|
||||
if (this.exists(fuzzySearchKey)) return fuzzySearchKey;
|
||||
|
||||
var bestScore = 0.0;
|
||||
var bestKey = null;
|
||||
|
||||
for (key in this.keys()) {
|
||||
var score = fuzzyMatchScore(key, fuzzySearchKey);
|
||||
if (score > bestScore) {
|
||||
bestScore = score;
|
||||
bestKey = key;
|
||||
}
|
||||
}
|
||||
|
||||
if (bestScore < threshold) {
|
||||
if (throwIfNone)
|
||||
throw 'No good match for $fuzzySearchKey in $this -- best was $bestKey with $bestScore';
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
#if (test || debug)
|
||||
trace('Fuzzy match $bestKey for $fuzzySearchKey score: $bestScore');
|
||||
#end
|
||||
|
||||
return bestKey;
|
||||
return FuzzyMapTools.bestMatch(this, fuzzySearchKey, throwIfNone);
|
||||
}
|
||||
|
||||
@:arrayAccess
|
||||
|
@@ -2,23 +2,58 @@ package kiss;
|
||||
|
||||
import haxe.Json;
|
||||
import haxe.ds.StringMap;
|
||||
using hx.strings.Strings;
|
||||
|
||||
typedef MapInfo = {
|
||||
file:String,
|
||||
matches:Map<String,Dynamic>
|
||||
};
|
||||
|
||||
/**
|
||||
* FuzzyMap is highly inefficient, so you may wish to memoize the matches that it makes before
|
||||
* releasing your project. FuzzyMapTools helps with this
|
||||
*/
|
||||
class FuzzyMapTools {
|
||||
static var serializingMaps = new Map<StringMap<Dynamic>, MapInfo>();
|
||||
|
||||
/**
|
||||
* FuzzyMap is highly inefficient, so you may wish to memoize the matches that it makes before
|
||||
* releasing your project. FuzzyMapTools.serializeMatches() helps with this
|
||||
*/
|
||||
public static function serializeMatches(m:StringMap<Dynamic>, file:String) {
|
||||
serializingMaps[m] = { file: file, matches: new Map() };
|
||||
}
|
||||
|
||||
public static function fuzzyMatchScore(key:String, fuzzySearchKey:String) {
|
||||
return 1 - (key.toLowerCase().getLevenshteinDistance(fuzzySearchKey.toLowerCase()) / Math.max(key.length, fuzzySearchKey.length));
|
||||
}
|
||||
|
||||
static var threshold = 0.4;
|
||||
|
||||
public static function bestMatch<T>(map:FuzzyMap<T>, fuzzySearchKey:String, ?throwIfNone=true):String {
|
||||
if (map.existsExactly(fuzzySearchKey)) return fuzzySearchKey;
|
||||
|
||||
var bestScore = 0.0;
|
||||
var bestKey = null;
|
||||
|
||||
for (key in map.keys()) {
|
||||
var score = fuzzyMatchScore(key, fuzzySearchKey);
|
||||
if (score > bestScore) {
|
||||
bestScore = score;
|
||||
bestKey = key;
|
||||
}
|
||||
}
|
||||
|
||||
if (bestScore < threshold) {
|
||||
if (throwIfNone)
|
||||
throw 'No good match for $fuzzySearchKey in $map -- best was $bestKey with $bestScore';
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
#if (test || debug)
|
||||
trace('Fuzzy match $bestKey for $fuzzySearchKey score: $bestScore');
|
||||
#end
|
||||
|
||||
return bestKey;
|
||||
}
|
||||
|
||||
@:allow(kiss.FuzzyMap)
|
||||
static function onMatchMade(m:StringMap<Dynamic>, key:String, value:Dynamic) {
|
||||
#if (sys || hxnodejs)
|
||||
|
@@ -36,6 +36,7 @@ class KissInterp extends Interp {
|
||||
variables.set("Math", Math);
|
||||
variables.set("Json", haxe.Json);
|
||||
variables.set("StringMap", InterpMap);
|
||||
variables.set("FuzzyMapTools", FuzzyMapTools);
|
||||
variables.set("StringTools", StringTools);
|
||||
variables.set("Path", haxe.io.Path);
|
||||
#if (sys || hxnodejs)
|
||||
|
Reference in New Issue
Block a user