Ich suche nach einer Fuzzy-Such-JavaScript-Bibliothek, um ein Array zu filtern. Ich habe versucht, fuzzyset.js und fuse.js zu verwenden , aber die Ergebnisse sind schrecklich (es gibt Demos, die Sie auf den verlinkten Seiten ausprobieren können).
Nachdem ich etwas über die Levenshtein-Entfernung gelesen habe, scheint es mir eine schlechte Annäherung an das zu sein, wonach Benutzer suchen, wenn sie tippen. Für diejenigen, die es nicht wissen, berechnet das System, wie viele Einfügungen , Löschungen und Ersetzungen erforderlich sind, damit zwei Zeichenfolgen übereinstimmen.
Ein offensichtlicher Fehler, der im Levenshtein-Demerau-Modell behoben ist, besteht darin, dass sowohl Blub als auch Boob der Glühbirne gleich ähnlich sind (für die jeweils zwei Substitutionen erforderlich sind). Es ist jedoch klar, dass die Glühbirne dem Blub ähnlicher ist als der Boob , und das Modell, das ich gerade erwähnte, erkennt dies, indem es Transpositionen zulässt .
Ich möchte dies im Zusammenhang mit der Textvervollständigung verwenden. Wenn ich also ein Array habe ['international', 'splint', 'tinder']
und meine Abfrage int ist , sollte International meiner Meinung nach einen höheren Rang als Schiene haben , obwohl Ersteres eine Punktzahl (höher = schlechter) von 10 hat gegen die 3 des letzteren.
Was ich also suche (und erstellen werde, wenn es nicht existiert), ist eine Bibliothek, die Folgendes tut:
- Gewichtet die verschiedenen Textmanipulationen
- Gewichtet jede Manipulation unterschiedlich, je nachdem, wo sie in einem Wort vorkommt (frühe Manipulationen sind teurer als späte Manipulationen).
- Gibt eine nach Relevanz sortierte Ergebnisliste zurück
Ist jemand auf so etwas gestoßen? Mir ist klar, dass StackOverflow nicht der richtige Ort ist, um nach Softwareempfehlungen zu fragen, aber implizit (nicht mehr!) Ist Folgendes: Denke ich richtig darüber nach?
Bearbeiten
Ich habe ein gutes Papier (pdf) zu diesem Thema gefunden. Einige Notizen und Auszüge:
Affine Bearbeitungsentfernungsfunktionen weisen einer Folge von Einfügungen oder Löschungen relativ geringere Kosten zu
die Monger-Elkan-Distanzfunktion (Monge & Elkan 1996), eine affine Variante der Smith-Waterman-Distanzfunktion (Durban et al. 1998) mit bestimmten Kostenparametern
Für die Smith-Waterman-Distanz (Wikipedia) : "Anstatt die Gesamtsequenz zu betrachten, vergleicht der Smith-Waterman-Algorithmus Segmente aller möglichen Längen und optimiert das Ähnlichkeitsmaß." Es ist der n-Gramm-Ansatz.
Eine weitgehend ähnliche Metrik, die nicht auf einem Edit-Distance-Modell basiert, ist die Jaro-Metrik (Jaro 1995; 1989; Winkler 1999). In der Literatur zu Datensatzverknüpfungen wurden gute Ergebnisse mit Varianten dieser Methode erzielt, die auf der Anzahl und Reihenfolge der gemeinsamen Zeichen zwischen zwei Zeichenfolgen basiert.
Eine Variante davon aufgrund von Winkler (1999) verwendet auch die Länge P des längsten gemeinsamen Präfixes
(scheinen hauptsächlich für kurze Saiten gedacht zu sein)
Für die Vervollständigung von Texten scheinen die Ansätze von Monger-Elkan und Jaro-Winkler am sinnvollsten zu sein. Winklers Hinzufügung zur Jaro-Metrik gewichtet die Wortanfänge effektiv stärker. Und der affine Aspekt von Monger-Elkan bedeutet, dass die Notwendigkeit, ein Wort zu vervollständigen (was einfach eine Folge von Ergänzungen ist), es nicht zu stark benachteiligt.
Fazit:
Das TFIDF-Ranking schnitt unter mehreren tokenbasierten Entfernungsmetriken am besten ab, und eine von Monge und Elkan vorgeschlagene abgestimmte affine-Gap-Editierdistanzmetrik schnitt unter mehreren String-Editierdistanzmetriken am besten ab. Eine überraschend gute Distanzmetrik ist ein schnelles heuristisches Schema, das von Jaro vorgeschlagen und später von Winkler erweitert wurde. Dies funktioniert fast so gut wie das Monge-Elkan-Schema, ist jedoch um eine Größenordnung schneller. Eine einfache Möglichkeit, die TFIDF-Methode und den Jaro-Winkler zu kombinieren, besteht darin, die in TFIDF verwendeten genauen Token-Übereinstimmungen durch ungefähre Token-Übereinstimmungen zu ersetzen, die auf dem Jaro-Winkler-Schema basieren. Diese Kombination ist im Durchschnitt etwas besser als Jaro-Winkler oder TFIDF und gelegentlich viel besser. Die Leistung kommt auch einer erlernten Kombination mehrerer der besten in diesem Dokument berücksichtigten Metriken nahe.
krole
kehrt die Eingabe nicht zurückFinal Fantasy V: Krile
, obwohl ich es gerne hätte. Es erfordert, dass alle Zeichen in der Abfrage im Ergebnis in derselben Reihenfolge vorhanden sind, was ziemlich kurzsichtig ist. Es scheint, dass die einzige Möglichkeit für eine gute Fuzzy-Suche darin besteht, eine Datenbank mit gängigen Tippfehlern zu haben.Antworten:
Gute Frage! Aber ich denke, anstatt zu versuchen, Levenshtein-Demerau zu modifizieren, ist es vielleicht besser, einen anderen Algorithmus auszuprobieren oder die Ergebnisse von zwei Algorithmen zu kombinieren / zu gewichten.
Es fällt mir auf, dass Levenshtein-Demerau exakten oder engen Übereinstimmungen mit dem "Startpräfix" kein besonderes Gewicht beimisst - aber Ihre offensichtlichen Benutzererwartungen würden dies tun.
Ich suchte nach "besser als Levenshtein" und fand unter anderem Folgendes:
http://www.joyofdata.de/blog/comparison-of-string-distance-algorithms/
Dies erwähnt eine Reihe von "String Distance" -Maßnahmen. Drei, die für Ihre Anforderung besonders relevant waren, wären:
Längster gemeinsamer Teilzeichenfolgenabstand: Mindestanzahl von Symbolen, die in beiden Zeichenfolgen entfernt werden müssen, bis die resultierenden Teilzeichenfolgen identisch sind.
q-Gramm-Abstand: Summe der absoluten Differenzen zwischen N-Gramm-Vektoren beider Strings.
Jaccard-Abstand: 1 miniert den Quotienten aus gemeinsam genutzten N-Gramm und allen beobachteten N-Gramm.
Vielleicht könnten Sie eine gewichtete Kombination (oder ein Minimum) dieser Metriken mit Levenshtein verwenden - gemeinsame Teilzeichenfolge, gemeinsames N-Gramm oder Jaccard bevorzugen alle stark ähnliche Zeichenfolgen - oder versuchen Sie es einfach mit Jaccard?
Abhängig von der Größe Ihrer Liste / Datenbank können diese Algorithmen mäßig teuer sein. Für eine von mir implementierte Fuzzy-Suche habe ich eine konfigurierbare Anzahl von N-Gramm als "Abrufschlüssel" aus der Datenbank verwendet und dann das teure Zeichenfolgenabstandsmaß ausgeführt, um sie in der bevorzugten Reihenfolge zu sortieren.
Ich habe einige Notizen zur Fuzzy-String-Suche in SQL geschrieben. Sehen:
quelle
Ich habe versucht, vorhandene Fuzzy-Bibliotheken wie fuse.js zu verwenden, und fand sie auch schrecklich. Deshalb habe ich eine geschrieben, die sich im Grunde wie die Suche von sublime verhält. https://github.com/farzher/fuzzysort
Der einzige Tippfehler, den es erlaubt, ist eine Transponierung. Es ist ziemlich solide (1k Sterne, 0 Ausgaben) , sehr schnell und behandelt Ihren Fall einfach:
quelle
Hier ist eine Technik, die ich einige Male angewendet habe ... Sie liefert ziemlich gute Ergebnisse. Tut aber nicht alles, wonach Sie gefragt haben. Dies kann auch teuer sein, wenn die Liste umfangreich ist.
Übergeben Sie zwei Zeichenfolgen,
string_similarity
denen eine Zahl zwischen0
und1.0
je nachdem, wie ähnlich sie sind, zurückgegeben wird. In diesem Beispiel wird Lo-Dash verwendetAnwendungsbeispiel ....
Auch ... habe eine Geige
Stellen Sie sicher, dass Ihre Konsole geöffnet ist oder Sie nichts sehen :)
quelle
Dies ist meine kurze und kompakte Funktion für Fuzzy Match:
quelle
Sie können einen Blick auf Atoms https://github.com/atom/fuzzaldrin/ lib werfen .
Es ist auf npm verfügbar, hat eine einfache API und hat bei mir gut funktioniert.
quelle
November 2019 Update. Ich fand Sicherung, um einige ziemlich anständige Upgrades zu haben. Ich konnte es jedoch nicht dazu bringen, Bools (dh OR-, AND- usw. Operatoren) zu verwenden, und ich konnte auch nicht die API-Suchoberfläche verwenden, um Ergebnisse zu filtern.
Ich habe Folgendes entdeckt
nextapps-de/flexsearch
: https://github.com/nextapps-de/flexsearch und ich glaube, es übertrifft bei weitem viele der anderen Javascript-Suchbibliotheken, die ich ausprobiert habe, und es unterstütztbool
das Filtern von Suchanfragen und Paginierungen.Sie können eine Liste von Javascript-Objekten für Ihre Suchdaten (dh Speicher) eingeben, und die API ist ziemlich gut dokumentiert: https://github.com/nextapps-de/flexsearch#api-overview
Bisher habe ich fast 10.000 Datensätze indiziert, und meine Suche erfolgt nahezu sofort. dh nicht wahrnehmbare Zeit für jede Suche.
quelle
Hier ist die Lösung von @InternalFX, aber in JS (ich habe es so geteilt):
quelle
Ich habe die Probleme mit der CoffeeScript-Bigram-Lösung von InternalFx behoben und daraus eine generische n-Gramm-Lösung gemacht (Sie können die Größe der Gramme anpassen).
Dies ist TypeScript, aber Sie können die Typanmerkungen entfernen und es funktioniert auch gut als Vanille-JavaScript.
Beispiele:
Probieren Sie es auf dem TypeScript-Spielplatz aus
quelle
jsfiddle http://jsfiddle.net/guest271314/QP7z5/
quelle
Schauen Sie sich mein Google Sheets-Add-On namens Flookup an und verwenden Sie diese Funktion:
Die Parameterdetails sind:
lookupValue
: der Wert, den Sie suchentableArray
: die Tabelle, die Sie durchsuchen möchtenlookupCol
: die Spalte, die Sie suchen möchtenindexNum
: Die Spalte, aus der Daten zurückgegeben werden sollenthreshold
: Die prozentuale Ähnlichkeit, unterhalb derer Daten nicht zurückgegeben werden solltenrank
: das n-te beste Spiel (dh wenn das erste Spiel nicht Ihren Wünschen entspricht)Dies sollte Ihren Anforderungen entsprechen ... obwohl ich mir bei Punkt 2 nicht sicher bin.
Weitere Informationen finden Sie auf der offiziellen Website .
quelle