Move FuzzyMap core functionality to FuzzyMapTools for reuse
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
package kiss;
|
package kiss;
|
||||||
|
|
||||||
import haxe.ds.StringMap;
|
import haxe.ds.StringMap;
|
||||||
|
import kiss.FuzzyMapTools;
|
||||||
|
|
||||||
using hx.strings.Strings;
|
using hx.strings.Strings;
|
||||||
|
|
||||||
@@ -20,37 +21,8 @@ abstract FuzzyMap<T>(StringMap<T>) from StringMap<T> to StringMap<T> {
|
|||||||
return this;
|
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 {
|
function bestMatch(fuzzySearchKey:String, ?throwIfNone=true):String {
|
||||||
if (this.exists(fuzzySearchKey)) return fuzzySearchKey;
|
return FuzzyMapTools.bestMatch(this, fuzzySearchKey, throwIfNone);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@:arrayAccess
|
@:arrayAccess
|
||||||
|
@@ -2,23 +2,58 @@ package kiss;
|
|||||||
|
|
||||||
import haxe.Json;
|
import haxe.Json;
|
||||||
import haxe.ds.StringMap;
|
import haxe.ds.StringMap;
|
||||||
|
using hx.strings.Strings;
|
||||||
|
|
||||||
typedef MapInfo = {
|
typedef MapInfo = {
|
||||||
file:String,
|
file:String,
|
||||||
matches:Map<String,Dynamic>
|
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 {
|
class FuzzyMapTools {
|
||||||
static var serializingMaps = new Map<StringMap<Dynamic>, MapInfo>();
|
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) {
|
public static function serializeMatches(m:StringMap<Dynamic>, file:String) {
|
||||||
serializingMaps[m] = { file: file, matches: new Map() };
|
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)
|
@:allow(kiss.FuzzyMap)
|
||||||
static function onMatchMade(m:StringMap<Dynamic>, key:String, value:Dynamic) {
|
static function onMatchMade(m:StringMap<Dynamic>, key:String, value:Dynamic) {
|
||||||
#if (sys || hxnodejs)
|
#if (sys || hxnodejs)
|
||||||
|
@@ -36,6 +36,7 @@ class KissInterp extends Interp {
|
|||||||
variables.set("Math", Math);
|
variables.set("Math", Math);
|
||||||
variables.set("Json", haxe.Json);
|
variables.set("Json", haxe.Json);
|
||||||
variables.set("StringMap", InterpMap);
|
variables.set("StringMap", InterpMap);
|
||||||
|
variables.set("FuzzyMapTools", FuzzyMapTools);
|
||||||
variables.set("StringTools", StringTools);
|
variables.set("StringTools", StringTools);
|
||||||
variables.set("Path", haxe.io.Path);
|
variables.set("Path", haxe.io.Path);
|
||||||
#if (sys || hxnodejs)
|
#if (sys || hxnodejs)
|
||||||
|
Reference in New Issue
Block a user