scala - 烫伤:成对比较字符串?

标签 scala hadoop edit-distance scalding

使用 Scalding 我需要:

  1. 按前 3 个字符对字符串字段进行分组
  2. 使用 edit-distance 指标 ( http://en.wikipedia.org/wiki/Edit_distance ) 比较每组中所有对的字符串
  3. 将结果写入 CSV 文件,记录为 string;字符串;距离

为了对字符串进行分组,我使用了 mapgroupBy,如下例所示:

import cascading.tuple.Fields
import com.twitter.scalding._

class Scan(args: Args) extends Job(args) {
  val output = TextLine("tmp/out.txt")

  val wordsList = List(
    ("aaaa"),
    ("aaabb"),
    ("aabbcc"),
    ("aaabccdd"),
    ("aaabbccdde"),
    ("aaabbddd"),
    ("bbbb"),
    ("bbbaaa"),
    ("bbaaabb"),
    ("bbbcccc"),
    ("bbbddde"),
    ("ccccc"),
    ("cccaaa"),
    ("ccccaabbb"),
    ("ccbbbddd"),
    ("cdddeee")
    )

  val orderedPipe =
    IterableSource[(String)](wordsList, ('word))
        .map('word -> 'key ){word:String => word.take(3)}
    .groupBy('key) {_.toList[String]('word -> 'x) }
        .debug
        .write(output)
}

结果我得到:

['aaa', 'List(aaabbddd, aaabbccdde, aaabccdd, aaabb, aaaa)']
['aab', 'List(aabbcc)']
['bba', 'List(bbaaabb)']
['bbb', 'List(bbbddde, bbbcccc, bbbaaa, bbbb)']
['ccb', 'List(ccbbbddd)']
['ccc', 'List(ccccaabbb, cccaaa, ccccc)']
['cdd', 'List(cdddeee)']

现在,在这个例子中,我需要计算列表中带有 aaa 键的字符串的编辑距离:

List(aaabbddd, aaabbccdde, aaabccdd, aaabb, aaaa)

此列表中所有带有 'bbb' 键的字符串的下一个:

List(bbbddde, bbbcccc, bbbaaa, bbbb)

等等

要计算每个组中所有字符串之间的编辑距离,我需要用我自己的函数替换 toList,我该怎么做?以及如何将函数的结果写入 CSV 文件?

谢谢!

更新

如何从Scalding Pipe获取List

toList 只是返回另一个 Pipe 所以我不能全部使用它:

  val orderedPipe =
    IterableSource[(String)](wordsList, ('word))
        .map('word -> 'key ){word:String => word.take(3)}
        .groupBy('key) {_.toList[String]('word -> 'x) }
        .combinations(2) //---ERROR! Pipe has no such method!
        .debug
        .write(output)

最佳答案

编辑距离可以按照wikipedia中的描述进行计算:

def editDistance(a: String, b: String): Int = {

    import scala.math.min

    def min3(x: Int, y: Int, z: Int) = min(min(x, y), z)

    val (m, n) = (a.length, b.length)

    val matrix = Array.fill(m + 1, n + 1)(0)

    for (i <- 0 to m; j <- 0 to n) {

        matrix(i)(j) = if (i == 0) j
                       else if (j == 0) i
                       else if (a(i-1) == b(j-1)) matrix(i-1)(j-1)
                       else min3(
                                 matrix(i - 1)(j) + 1,
                                 matrix(i)(j-1) + 1,
                                 matrix(i - 1)(j - 1) + 1) 
    }

    matrix(m)(n)
}

查找列表元素的成对编辑距离:

def editDistances(list: List[String]) = {

    list.combinations(2).toList.map(x => (x(0), x(1), editDistance(x(0), x(1))))
}

在 groupBy 中使用它:

  val orderedPipe =
      IterableSource[(String)](wordsList, ('word))
      .map('word -> 'key ){word:String => word.take(3)}
      .groupBy('key) {_.mapList[String, List[(String, String, Int)]]('word -> 'x)(editDistances)}
      .debug
      .write(output)    

就写入 csv 格式而言,您可以简单地使用 com.twitter.scalding.Csv 类。

写入(Csv(输出文件))

关于scala - 烫伤:成对比较字符串?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24758112/

相关文章:

hadoop - hive -e 带分隔符

python - 如何将一列的不同行与 pandas 中的 Levenshtein 距离度量进行比较?

java - scala如何使用java文件中定义的类或其他东西?

scala - Scala 构造函数和枚举的问题

scala - Haskell : ".... there is no single type that contains both 2 and ' b'. 的温和介绍“我不能制作这样的类型吗?

hadoop - 如何在hadoop-1.0.4中禁用作业设置和作业清理任务

hadoop - 在Oozie中编辑YARN的类路径

algorithm - 使用 Base64 编码作为检测更改的机制

string - 有效地计算一个字符串和一大组其他字符串之间的编辑距离?

java - 从具有超过 254 个字段的模式 avro 生成平面案例类