如何在惯用的Scala中编写嵌套循环?

如何在惯用的Scala中编写嵌套循环?,scala,Scala,这是我的伪代码,显然这不是惯用的scala,因为我使用了很多可变变量和循环 我的目标是以函数的方式将其转换为惯用的scala 该算法的目标是给定一个字符串列表,对其本身进行N^2比较,以使用编辑距离查找匹配项。因为编辑距离检查是示例,所以我希望避免对已检查的字符串对执行编辑距离检查 def pairwisecomp(block: Iterable[String]): List[(String, String)] = { var matches = new ListBuffer[(Stri

这是我的伪代码,显然这不是惯用的scala,因为我使用了很多可变变量和循环

我的目标是以函数的方式将其转换为惯用的scala

该算法的目标是给定一个字符串列表,对其本身进行N^2比较,以使用编辑距离查找匹配项。因为编辑距离检查是示例,所以我希望避免对已检查的字符串对执行编辑距离检查

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会慢一些,因为循环会查看其中的所有值。