gpt4 book ai didi

java - 使用部分单词匹配而不是余弦相似度来搜索java中2个字符串的相似度

转载 作者:行者123 更新时间:2023-11-30 01:43:03 25 4
gpt4 key购买 nike

嗨,我想通过其他字符串中出现的部分单词来比较 2 个字符串。例如:我有 4 个字符串:

A) "white snow ball"
B) "super exciting"
C) "white image superdupercold"
D) "cold"

用户通过此字符串搜索“super Cold White Snow”结果应按以下顺序返回:

C, A, D, B

因为 B 在总共 2 个单词中只有一个匹配“super”(相似度 = 50%),而 D 在总共 1 个单词中只有一个匹配“cold”(相似度 = 100%)。 A 有 2 场比赛“白色”和“雪”,C 有 3 场比赛但是,如果我使用余弦相似度,它的排名会有所不同: results of cosine similarity

另一个例子:如果用户通过这个字符串“super”搜索,那么结果应该按以下顺序返回:B、C

我认为这可以通过正则表达式和字符串分割来解决。有没有什么好的和干净的方法来用java编写它?

最佳答案

对于每个搜索字符串,使用 haystack.split("\\s+") 将其拆分为单词( \\s+ 是正则表达式,表示“字符串由空格分隔”)。

然后,要获得“分数”,您需要 2 个数字:匹配的单词数以及总共有多少个单词。您首先按降序排序,最后按升序排序,这会得到您似乎想要的行为。

String[] needle = "super cold white snow".split("\\s+");
String[] haystack = "white image superdupercold".split("\\s+");
int matchedWords = 0, totalWords = haystack.length;
for (String n : needle) {
boolean found = false;
for (String hay : haystack) {
if (hay.contains(n)) {
found = true;
break;
}
}
if (found) matchedWords++;
}

对于每根针,您现在最终会得到 2 个分数:matchedWords 和totalWords。

对于任意 2 个这样的分数对,获胜者是具有较高匹配单词的那个; TotalWords 充当决胜局,其作用相反(totalWords 较低者获胜)。

有多种方法可以尝试表达这一点。一个简单的技巧是将所有这些“编码”为一个长值:

private static final long MULTIPLIER = 0x100000000L;
long score = MULTIPLIER * matchedWords + (Integer.MAX_VALUE - totalWords);

现在更高得分的针是最好的答案。

另一种选择是创建一个代表针的类以及两个分数,将所有结果放入列表中,然后对列表进行排序:

@Value
class Result { String needle; int words, total; }

list.sort(
Comparator.comparing(Result::getWords).reversed().
thenComparing(Comparator.comparing(Result::getTotal));

list.stream().map(Result::getNeedle).forEach(System.out::println);

注意:如果目标是非常有效地做到这一点,以便您可以快速地处理几十万个干草堆中的一根针,那么答案就在于单词搜索解决方案,例如 postgres tsvectors 或像 Lucene 这样的库。 .

这些代码片段中使用的类型:

  • Lombok 的 @Value
  • java.util.Comparator

关于java - 使用部分单词匹配而不是余弦相似度来搜索java中2个字符串的相似度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59250470/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com