【问题标题】:How to implement Levenshtein Distance Algorithm in Scala如何在 Scala 中实现 Levenshtein 距离算法
【发布时间】:2021-07-03 00:38:25
【问题描述】:

我有一个文本文件,其中包含有关发件人和消息的信息,格式为发件人,消息。我想使用阈值为 70% 的 Levenshtein 距离算法,并希望将类似的消息存储到地图中。在地图中,我的键是String,值是List[String]

例如我的要求是:如果我的消息是 abc、bcd、cdf。

第 1 步: 首先,我应该将消息“abc”添加到列表中。 map.put("Group1",abc.toList)

第二步:接下来,我应该比较'bcd'(第二条消息)和'abc'(第一条消息)。如果它们达到 70% 的阈值,那么我应该将“bcd”添加到列表中。现在,“abc”和“bcd”被添加到名为“Group1”的同一个键下。

第 3 步: 现在,我应该从 Map 中获取所有元素。目前 G1 只有 2 个值(abc,bcd),接下来将当前消息 'cdf' 与 'abc' 或 'bcd' 进行比较(因为 'abc' 和 'bcd' 与它们中的任何一个比较就足够了)

步骤4:如果没有达到阈值,我应该创建一个新的键“Group2”并将该消息添加到列表等等。

70% 的阈值意味着,例如:

message1:尊敬的客户!您的手机号码 9032412236 已成功充值 500.00 印度卢比

message2:尊敬的客户!您的手机号码 7999610201 已成功充值 500.00 印度卢比

这里,这两者之间的 Levenshtein 距离是 8。我们可以在这里查看:https://planetcalc.com/1721/

需要进行8次编辑,(message1.length+message2.length)/2中有8个字符不匹配

如果我假设第一条消息是 100 个字符,第二条消息是 100 个字符,那么平均长度是 100,在 100 个字符中,有 8 个字符不匹配,这意味着准确度是 92%,所以在这里,我应该保持阈值 70%。

如果 Levenshtein 距离匹配至少 70%,则认为它们相似。

我正在使用以下库:

libraryDependencies += "info.debatty" % "java-string-similarity" % "2.0.0"

我的代码:

import org.apache.spark.{SparkConf, SparkContext}
import scala.collection.mutable.ListBuffer

object Demo {
  def main(args: Array[String]): Unit = {
    val conf = new SparkConf().setMaster("local").setAppName("My App")
    val sc = new SparkContext(conf)
    val inputFile = "D:\\MyData.txt"
    val data = sc.textFile(inputFile)
    val data2 = data.map(line => {
      val arr = line.split(","); (arr(0), arr(1))
    })
    val grpData = data2.groupByKey()
    val myMap = scala.collection.mutable.Map.empty[String, List[String]]
    for (values <- grpData.values.collect) {
      val list = ListBuffer[String]()
      for (value <- values) {
        println(values)
        if (myMap.isEmpty) {
          list += value
          myMap.put("G1", list.toList)
        } else {
          val currentMsg = value
          val valuePartOnly = myMap.valuesIterator.toString()
          for (messages <- valuePartOnly) {
            def levenshteinDistance(currentMsg: String, messages: String) = {
              ???//TODO: Implement distance
            }
          }
        }
      }
    }
  }
}

在 else 部分之后,我不知道如何开始使用这个算法。

我没有任何输出样本。所以,我已经一步一步地解释了。

请从第 1 步到第 4 步检查。

谢谢。

【问题讨论】:

  • 您好,欢迎来到 Stackoverflow。你已经尝试过什么了吗?到目前为止您遇到过什么问题吗?您是否尝试过任何代码 sn-p?谢谢
  • 示例输入是一张图片,因此无法复制粘贴到我们的工作环境中。如果没有所需输出的样本,我们如何知道我们建议的答案是否正确?如果我的解决方案不正确,你应该告诉我它在哪里产生了不好的结果。
  • 由于我对堆栈溢出很陌生,我不知道如何在这里上传我的输入文件,对此我很抱歉,我已经解释了需要做什么,但没有给出任何输出样本。
  • 好的,我会检查并更新你。

标签: scala apache-spark levenshtein-distance


【解决方案1】:

我不太确定我没有尝试过的下一个代码,但我希望它能证明这个想法:

import org.apache.spark.{SparkConf, SparkContext}
import scala.collection.mutable.ListBuffer

object Demo {
  def main(args: Array[String]): Unit = {
    val conf = new SparkConf().setMaster("local").setAppName("My App")
    val distance: Levenshtein = new Levenshtein(); //Create object for calculation distance
    
    def levenshteinDistance(left: String, right: String): Double = {
      // I'm not really certain about this, how you would like to calculate relative distance?
      // Relatevly to string with max size, min size, left or right?
      l.distance(left, right) / Math.max(left.size, right.size) 
    }
    
    val sc = new SparkContext(conf)
    val inputFile = "D:\\MyData.txt"
    val data = sc.textFile(inputFile)
    val data2 = data.map(line => {
      val arr = line.split(","); (arr(0), arr(1))
    })
    val grpData = data2.groupByKey()
    val messages = scala.collection.mutable.Map.empty[String, List[String]]
    var group = 1
    for (values <- grpData.values.collect) {
      val list = ListBuffer[String]()
      for (value <- values) {
        println(values)
        if (messages.isEmpty) {
          list += value
          messages.put("G$group", list.toList)
        } else {
          val currentMsg = value
          val group = messages.values.find {
            case(key, messages) => messages.forall(message => levenshteinDistance(currentMsg, message) <= 0.7)
          }._1.getOrElse {
            group += 1
            "G$group"
          }
          val groupMessages = messages.getOrEse(group, ListBuffer.empty[String])
          groupMessages.append(currentMsg)
          messages.put(currentMsg, groupMessages)
        }
      }
    }
  }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-04-23
    • 2014-04-20
    • 1970-01-01
    • 2014-04-14
    • 1970-01-01
    • 2013-01-15
    • 2016-08-09
    相关资源
    最近更新 更多