【问题标题】:Check to see if two strings are very similar (similar characters, patterns, etc.)检查两个字符串是否非常相似(相似的字符、模式等)
【发布时间】:2021-02-05 23:52:02
【问题描述】:

我习惯于在 Ruby 中对大量字符串进行精确匹配检查,但我想知道是否有办法让这个过程更高效。

例如,我从一个区域获取数据并将其与活动记录中的数据进行比较。如果www.domain.com 在一个位置,但domain.com 在另一个位置,我可以确定的唯一方法是在一个位置删除www 或在另一个位置添加它。

有没有办法智能地判断两条数据是否相似?

在上面的例子中,14 个字符中有 10 个(或 71.42%)是相似的,所以我认为可以安全地假设这两个记录属于链接,因为它们只是略有不同。

有没有一种方法可以明智地做出这种决定?

【问题讨论】:

  • dowmawiwn.com?通常,您会将事物规范化为更简单的一致形式。
  • 是的,我们通常就是这样做的,但是对于这个特定的项目,我必须找到相似的数据并使它们保持一致,这样才能继续下去。
  • 可能与Ruby compare two strings similarity percentage 重复,它链接了一些类似的问题,但这是最新的。

标签: ruby


【解决方案1】:

Damerau-Levenshtein 距离的模糊匹配

任何类型的模糊匹配都会在某种程度上取决于您选择查看数据的方式。对于这样的事情,您可以查看 Levenshtein 距离的许多变体之一,例如Damerau-Levenshtein。您可以调整 MIN_SIMILARITY_PERCENT 来调整相似度指数,该指数是使用编辑距离作为对中最长单词中找到的字符的百分比来计算的。

require 'damerau-levenshtein'

class SimilarityIndex
  MIN_SIMILARITY_PERCENT = 70.0

  attr_reader :similarity_idx, :words

  def initialize word1, word2
    @words = word1, word2
    similar?
  end
  
  def edit_distance
    DamerauLevenshtein.distance *@words
  end

  def longest_word_length
    @words.max_by(&:length).size
  end

  def similar?
    e = edit_distance
    l = longest_word_length.to_f
    @similarity_idx = ((1 - (e/l)) * 100).round 2
    @similarity_idx >= MIN_SIMILARITY_PERCENT
  end
end

您可以使用一些测试数据来验证这一点。例如:

word_pairs = %w[
  www.domain.com
  domain.com

  www.example.com
  foobarbaz.example.com
]

word_pairs.each_slice(2).map do |word1, word2|
  s = SimilarityIndex.new word1, word2
  { words: s.words, similarity_idx: s.similarity_idx, similar?: s.similar? }
end

此测试数据生成以下结果:

[{:words=>["www.domain.com", "domain.com"],
  :similarity_idx=>71.43,
  :similar?=>true},
 {:words=>["www.example.com", "foobarbaz.example.com"],
  :similarity_idx=>57.14,
  :similar?=>false}]

【讨论】:

    猜你喜欢
    • 2020-10-05
    • 1970-01-01
    • 1970-01-01
    • 2019-07-05
    • 2015-10-17
    • 1970-01-01
    • 2019-04-18
    • 2015-10-30
    • 1970-01-01
    相关资源
    最近更新 更多