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

时间:2016-10-24 00:07:54

标签: scala

这是我的伪代码,显然这不是惯用的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
  }

4 个答案:

答案 0 :(得分:3)

我认为它可以缩短,我认为代码的打击与你写的完全相同。

NULL

编辑: 在理解方面可能更简单。

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

答案 1 :(得分:1)

如果没有工作editDistance()来测试它很难知道,但我认为这与你所追求的很接近。

def pairwisecomp(block: Seq[String]): List[List[String]] = {
  block.combinations(2).filter(editDistance(str1, str2) < 2).toList
}

请注意,我更改了block集合类型,以便我可以使用combinations()方法。还有其他方法可以实现这一目标。

答案 2 :(得分:1)

'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'足够接近,则产生该对。

答案 3 :(得分:0)

我认为你可以使用for-comprehension:

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)
}