如何将相似的单词合并为一个?

时间:2015-07-25 09:55:15

标签: ruby algorithm

similar_text gem可以计算单词的成对相似度。我想将相似度大于50%的单词合并为一个,并保持最长的单词。

  • 原始

    [
      "iphone 6",
      "iphone 5c",
      "iphone 6",
      "macbook air",
      "macbook",
    ]
    
  • 预期

    [
      "iphone 5c",
      "macbook air",
    ]
    

但我不知道如何有效地过滤预期结果的算法。

2 个答案:

答案 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

有关如何在比赛中找到组的答案,请参阅:

Finding All Connected Components of an Undirected Graph

答案 1 :(得分:0)

首先 - 没有有效的方法可以做到这一点,因为你必须计算长列表上可能需要很长时间的所有码头。

说完了......

我不熟悉这个特定的宝石,但我认为它会给你两个单词之间的某种距离(越小越好)或单词相同的概率(更高的结果更好)。让我们选择距离,因为将算法改为概率是微不足道的。

这只是一个您可能会觉得有用的算法描述。它帮助了我的类似案例。

我建议将所有单词放在二维数组中作为行和列的标题。如果你有N个单词,你需要NxN矩阵。

在每个单元格中放置单词之间的计算距离(行和列标题)。

您将获得所有可能距离的矩阵。请记住,在这种情况下,我们会寻找单词之间的最小距离。

因此,对于每一行,寻找最小单元格(不是具有零值的单元格,即单词与自身的距离)。

如果此min大于某个阈值,则该单词没有相似的单词。如果没有,请查找此行中距离达到阈值的所有单词(实际上您可以跳过上一个阶段并执行此搜索)。 您找到的所有单词都属于同一组。寻找最长的并在你正在建立的新列表中使用它。

另请注意索引,您找到了最小距离,并跳过与索引(因此您不会将相同的词添加到不同的组)。< / p>