我有一些字符串列表,例如:
["foo bar SOME baz TEXT bob",
"SOME foo bar baz bob TEXT",
"SOME foo TEXT",
"foo bar SOME TEXT baz",
"SOME TEXT"]
我希望它按照SOME TEXT
子串的精确度排序(大写并不重要)。像这样的顺序:
["SOME TEXT",
"foo bar SOME TEXT baz",
"SOME foo TEXT",
"foo bar SOME baz TEXT bob",
"SOME foo bar baz bob TEXT"]
这个想法是 - 最好的分数得到与子串字位置最匹配的字符串。对于更大量的"马虎"子字符串之间的单词 - 它得到的排序越低
我找到了一些像fuzzyset或Levenshtein distance这样的库,但我不确定这是我需要的。根据我的理解,我知道我要排序的确切子字符串和那些libs搜索相似的单词。
实际上我需要在我的Django项目中进行一些数据库查询(Postgresql)之后进行此类操作。我已经尝试使用其ORM进行全文搜索,但没有得到相关的排序顺序(它不能计算子字符串之间的距离)。接下来我尝试了Haystack + Whoosh,但此时此刻并没有找到如何做到这一点的信息。所以现在的想法是获取查询集,然后将其排序出数据库(是的,我知道这可能是一个糟糕的决定,但是现在我希望它只是工作)。但是,如果有人告诉我如何在任何技术中做到这一点,我在这里提到 - 这也将是非常酷。谢谢!
P.S。子串的长度应该是最多20个字符串中的2-10个字。
答案 0 :(得分:5)
您可以使用difflib.SequenceMatcher来实现与所需输出非常相似的内容:
>>> 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']
如果你不能说明唯一的区别是两个元素"foo bar SOME TEXT baz"
和"SOME foo TEXT"
的位置与你想要的输出相比是交换的。
答案 1 :(得分:1)
查看友好社区sorting tutorial。您需要使用密钥进行排序。这是一个微不足道的功能,可以给你这个想法;它找到两个单词之间的距离,并将其作为差异指标返回。
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)
输出:
foo bar SOME TEXT baz
SOME TEXT
foo bar SOME baz TEXT bob
SOME foo TEXT
SOME foo bar baz bob TEXT
答案 2 :(得分:0)
这是我的看法。
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)
输出:
['SOME TEXT', 'foo bar SOME TEXT baz', 'SOME foo TEXT', 'foo bar SOME baz TEXT bob', 'SOME foo bar baz bob TEXT']
所以我们所做的就是根据主要权重将列表排序为“SOME”和“TEXT”之间的距离,并对字符串中“SOME”的出现进行一些小的权重。
另一种更长的方法是首先根据SOME和TEXT之间的距离对列表进行分组。然后根据“SOME”的位置对每个组进行排序。