使用 Scalding 我需要:
- 按前 3 个字符对字符串字段进行分组
- 使用
edit-distance
指标 ( http://en.wikipedia.org/wiki/Edit_distance ) 比较每组中所有对的字符串 - 将结果写入 CSV 文件,记录为
string;字符串;距离
为了对字符串进行分组,我使用了 map
和 groupBy
,如下例所示:
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/