similar_text
gem可以计算单词的成对相似度。我想将相似度大于50%的单词合并为一个,并保持最长的单词。
原始
[
"iphone 6",
"iphone 5c",
"iphone 6",
"macbook air",
"macbook",
]
预期
[
"iphone 5c",
"macbook air",
]
但我不知道如何有效地过滤预期结果的算法。
答案 0 :(得分:0)
这不是一个微不足道的问题,也不是你正在寻找的100%。
特别是如何处理传递相似性:如果 a 类似于 b 而 b 类似于 c ,在同一组中是 a 和 c (即使它们彼此不相似?)
这是一段代码,您可以在其中找到数组中的所有类似对:
def find_pairs(ar)
ar.product(ar).reject{|l,r| l == r}.map(&:sort).uniq
.map{|l,r| [[l,r],l.similar(r)]}
.reject{|pair, similarity| similarity < 50.0}
.map{|pair, _| pair}
end
有关如何在比赛中找到组的答案,请参阅:
答案 1 :(得分:0)
首先 - 没有有效的方法可以做到这一点,因为你必须计算长列表上可能需要很长时间的所有码头。
说完了......
我不熟悉这个特定的宝石,但我认为它会给你两个单词之间的某种距离(越小越好)或单词相同的概率(更高的结果更好)。让我们选择距离,因为将算法改为概率是微不足道的。
这只是一个您可能会觉得有用的算法描述。它帮助了我的类似案例。
我建议将所有单词放在二维数组中作为行和列的标题。如果你有N个单词,你需要NxN矩阵。
在每个单元格中放置单词之间的计算距离(行和列标题)。
您将获得所有可能距离的矩阵。请记住,在这种情况下,我们会寻找单词之间的最小距离。
因此,对于每一行,寻找最小单元格(不是具有零值的单元格,即单词与自身的距离)。
如果此min大于某个阈值,则该单词没有相似的单词。如果没有,请查找此行中距离达到阈值的所有单词(实际上您可以跳过上一个阶段并执行此搜索)。 您找到的所有单词都属于同一组。寻找最长的并在你正在建立的新列表中使用它。
另请注意列索引,您找到了最小距离,并跳过行与索引(因此您不会将相同的词添加到不同的组)。< / p>