如何在惯用的Scala中编写嵌套循环?
这是我的伪代码,显然这不是惯用的scala,因为我使用了很多可变变量和循环 我的目标是以函数的方式将其转换为惯用的scala 该算法的目标是给定一个字符串列表,对其本身进行N^2比较,以使用编辑距离查找匹配项。因为编辑距离检查是示例,所以我希望避免对已检查的字符串对执行编辑距离检查如何在惯用的Scala中编写嵌套循环?,scala,Scala,这是我的伪代码,显然这不是惯用的scala,因为我使用了很多可变变量和循环 我的目标是以函数的方式将其转换为惯用的scala 该算法的目标是给定一个字符串列表,对其本身进行N^2比较,以使用编辑距离查找匹配项。因为编辑距离检查是示例,所以我希望避免对已检查的字符串对执行编辑距离检查 def pairwisecomp(block: Iterable[String]): List[(String, String)] = { var matches = new ListBuffer[(Stri
def pairwisecomp(block: Iterable[String]): List[(String, String)] = {
var matches = new ListBuffer[(String, String)]
// pseudo code; not intended to be valid scala
for (var i = 0; i < block.size; i++) {
val str1 = block[i]
// iterate from i because no need to go backwards to compare
for (var j = i+1; j < block.size; j++) {
val str2 = block[j]
// check edit distance
// if less than 2, append into the matches
if (editDistance(str1, str2) < 2) {
matches.append((str1, str2))
}
}
}
return matches.toList
}
我认为它可以被缩短,但是我认为代码吹做的和你写的完全一样
block.flatMap{ str1 =>
block.zipWithIndex.filter{ case (elem,index) => index > i}.map{ case (str2,index) =>
((str1,str2),editDistance(str1,str2) < 2)
}.filter{_.2}.map{_1}
}.toList
编辑:
这在理解上可能更简单
val b = block.zipWithIndex
(for {
(str1,outerIndex) <- b
(str2,innerIndex) <- b if innerIndex > outerIndex && editDistance(str1,str2) < 2
} yield (str1,str2)).toList
我认为它可以被缩短,但是我认为代码吹做的和你写的完全一样
block.flatMap{ str1 =>
block.zipWithIndex.filter{ case (elem,index) => index > i}.map{ case (str2,index) =>
((str1,str2),editDistance(str1,str2) < 2)
}.filter{_.2}.map{_1}
}.toList
编辑:
这在理解上可能更简单
val b = block.zipWithIndex
(for {
(str1,outerIndex) <- b
(str2,innerIndex) <- b if innerIndex > outerIndex && editDistance(str1,str2) < 2
} yield (str1,str2)).toList
如果没有一个有效的测试距离,很难知道,但我认为这已经接近你想要的了
def pairwisecomp(block: Seq[String]): List[List[String]] = {
block.combinations(2).filter(editDistance(str1, str2) < 2).toList
}
请注意,我更改了块集合类型,以便可以使用组合方法。还有其他方法可以实现这一点。如果没有一个工作的editDistance来测试,很难知道,但我认为这已经接近你想要的了
def pairwisecomp(block: Seq[String]): List[List[String]] = {
block.combinations(2).filter(editDistance(str1, str2) < 2).toList
}
请注意,我更改了块集合类型,以便可以使用组合方法。实现这一点还有其他方法。'tails'是你的朋友:
def tryIt(): Unit = {
def editDistance(v1: (String, Int), v2: (String, Int)): Int = {
val (_, d1) = v1
val (_, d2) = v2
Math.abs(d1-d2)
}
val src = Seq (("C", 3), ("D", 4), ("A", 1), ("B", 2), ("E", 5), ("F", 6))
val res = for {
(h::tl) <- src.tails
t <- tl if editDistance(h ,t) < 2
} yield (h,t)
res.foreach {case (r1, r2) => println(s"$r1, $r2")}
}
h::tl是输入中每个元素h加上它后面的所有元素tl的一系列。从中比较尾部序列tl中的每个元素“t”。如果“h”和“t”足够接近,则产生该对。'tails'是您的朋友:
def tryIt(): Unit = {
def editDistance(v1: (String, Int), v2: (String, Int)): Int = {
val (_, d1) = v1
val (_, d2) = v2
Math.abs(d1-d2)
}
val src = Seq (("C", 3), ("D", 4), ("A", 1), ("B", 2), ("E", 5), ("F", 6))
val res = for {
(h::tl) <- src.tails
t <- tl if editDistance(h ,t) < 2
} yield (h,t)
res.foreach {case (r1, r2) => println(s"$r1, $r2")}
}
h::tl是输入中每个元素h加上它后面的所有元素tl的一系列。从中可以比较尾部序列tl中的每个元素“t”。如果“h”和“t”足够接近,则产生该对。我想你可以用a来理解这一点:
def pairwisecompII(block: Vector[String]): Seq[(String, String)] = {
for {
i ← block.indices
str1 = block(i)
j ← i + 1 until block.size
str2 = block(j)
if editDistance(str1, str2) < 2
} yield (str1, str2)
}
我想你可以用a来理解这一点:
def pairwisecompII(block: Vector[String]): Seq[(String, String)] = {
for {
i ← block.indices
str1 = block(i)
j ← i + 1 until block.size
str2 = block(j)
if editDistance(str1, str2) < 2
} yield (str1, str2)
}
block.zipWithIndex.filter{case elem,index=>index>i}因此对于嵌套循环,这是在某个索引处开始迭代的最佳时机?您不需要改为执行block.view.zipWithIndex吗?实际上,scala for只是foreach、flatMap、map和filter方法的语法糖。换句话说,代码可以写成for-comprehensions.and我猜block.view.zipWithIndex比较慢,因为循环查找其中的所有值。block.zipWithIndex.filter{case elem,index=>index>I}因此,对于嵌套循环,这是立即开始在某个索引处迭代的方法?您不需要改为执行block.view.zipWithIndex吗?实际上,scala for只是foreach、flatMap、map和filter方法的语法糖。换句话说,代码可以写成for-comprehensions.and,我猜block.view.zipWithIndex会慢一些,因为循环会查看其中的所有值。