2017-12-06 2 views
1

Ich habe einige Liste von Strings, zum Beispiel:
Python: Wie sortiere ich eine Liste von Strings nach Substring-Relevanz?

["foo bar SOME baz TEXT bob", 
"SOME foo bar baz bob TEXT", 
"SOME foo TEXT", 
"foo bar SOME TEXT baz",  
"SOME TEXT"] 

Ich will es durch Exaktheit zu SOME TEXT Teilzeichenfolge sortiert werden (Großschreibung spielt keine Rolle). So etwas wie diese Reihenfolge:

["SOME TEXT", 
"foo bar SOME TEXT baz", 
"SOME foo TEXT", 
"foo bar SOME baz TEXT bob", 
"SOME foo bar baz bob TEXT"] 

Die Idee ist - das beste Ergebnis erhält die Saite mit der besten Übereinstimmung Worten Position zu String. Und für eine größere Anzahl von "schlampigen" Wörtern zwischen den Wörtern der Teilstrings - die niedrigere Reihenfolge, die es bekommt.

Ich habe einige Bibliotheken wie fuzzyset oder Levenshtein distance gefunden, aber ich bin mir nicht sicher, das ist was ich brauche. Ich kenne die genaue Teilzeichenfolge nach dem, was ich sortieren möchte, und diese Bibliotheken durchsuchen die ähnlichen Wörter, so wie ich es verstanden habe.

Eigentlich muss ich diese Sortierung nach einer Datenbankabfrage (Postgresql) in meinem Django-Projekt tun. Ich habe bereits Volltextsuche mit seinem ORM versucht, aber diese relevante Sortierreihenfolge nicht erhalten (es zählt nicht den Abstand zwischen Substring-Wörtern). Als nächstes habe ich versucht, Haystack + Whoosh, aber auch in diesem Moment nicht finden, wie man diese Art dort tun. Die Idee ist nun, die Abfrage zu setzen und sie als nächstes aus der Datenbank zu sortieren (ja, ich weiß, dass das eine schlechte Entscheidung sein könnte, aber jetzt will ich, dass es einfach funktioniert). Aber wenn mir irgendjemand sagt, wie man das in irgendeiner der Technologien macht, habe ich hier erwähnt - das wird auch super cool sein. Vielen Dank!

p.s. Die Länge der Teilzeichenfolge sollte 2-10 Wörter in maximal 20 Wortfolgen betragen.

Antwort

3

Sie können difflib.SequenceMatcher verwenden, etwas sehr ähnlich zu den gewünschten Ausgang zu erreichen:

>>> import difflib 
>>> l = ["foo bar SOME baz TEXT bob", "SOME foo bar baz bob TEXT", "SOME foo TEXT", "foo bar SOME TEXT baz", "SOME TEXT"] 
>>> sorted(l, key=lambda z: difflib.SequenceMatcher(None, z, "SOME TEXT").ratio(), reverse=True) 
['SOME TEXT', 'SOME foo TEXT', 'foo bar SOME TEXT baz', 'foo bar SOME baz TEXT bob', 'SOME foo bar baz bob TEXT'] 

Wenn Sie der einzige Unterschied nicht sagen kann, ist, dass die Position der beiden Elemente "foo bar SOME TEXT baz" und "SOME foo TEXT" vertauscht sind im Vergleich zu Ihre gewünschte Ausgabe.

+1

Das ist eine interessante Klasse, die mir nicht bekannt war. +1. –

+1

Ja, das funktioniert perfekt! Vielen Dank! p.s.Btw difflib war die dritte Bibliothek, die ich gefunden habe, aber vergessen habe, es hier zu erwähnen (und auch nicht, wie man es richtig benutzt). :) – Chiefir

1

Sehen Sie Ihre freundliche Nachbarschaft sorting tutorial. Du brauchst eine Art mit einem Schlüssel. Hier ist eine triviale Funktion, um Ihnen die Idee zu geben; es findet den Abstand zwischen den zwei Wörtern und gibt das als Differenzmetrik zurück.

sentence = ["foo bar SOME baz TEXT bob", 
      "SOME foo bar baz bob TEXT", 
      "SOME foo TEXT", 
      "foo bar SOME TEXT baz", 
      "SOME TEXT"] 

def match_score(sentence): 
    some_pos = sentence.find("SOME") 
    text_pos = sentence.find("TEXT") 
    return abs(text_pos - some_pos) 

sentence.sort(key = lambda x: match_score(x)) 

for item in sentence: 
    print(item) 

Ausgang:

foo bar SOME TEXT baz 
SOME TEXT 
foo bar SOME baz TEXT bob 
SOME foo TEXT 
SOME foo bar baz bob TEXT 
0

Hier ist mein nehmen auf sie.

l = ["foo bar SOME baz TEXT bob", 
"SOME foo bar baz bob TEXT", 
"SOME foo TEXT", 
"foo bar SOME TEXT baz",  
"SOME TEXT"] 

l.sort(key=lambda x: (x.find("SOME")-x.find("TEXT"))*0.9-0.1*x.find("SOME"), reverse=True) 

print(l) 

OUTPUT:

['SOME TEXT', 'foo bar SOME TEXT baz', 'SOME foo TEXT', 'foo bar SOME baz TEXT bob', 'SOME foo bar baz bob TEXT'] 

Also, was wir haben die Liste sortiert ist getan basierend auf Hauptgewicht auf den Abstand zwischen „SOME“ und „TEXT“ und einige kleinere Gewicht auf das Auftreten von „SOME "in der Schnur.

Ein weiterer längerer Weg wäre, zuerst die Liste basierend auf ihrer Entfernung zwischen SOME und TEXT zu gruppieren. Und dann sortieren Sie jede Gruppe basierend auf der Position von "SOME".

+0

Was bedeuten diese 0.9-0.1? Wie kann dies mit 3 + Wörter Teilstring verwendet werden? – Chiefir

Verwandte Themen