首页 文章

用于嵌套循环的惯用Scala

提问于
浏览
2

我正在尝试编写惯用的scala代码来遍历两个列表列表,并生成一个仅包含两个列表差异的新列表 .

在程序Scala我会做这样的事情:

val first: List[List[Int]]  = List(List(1,2,3,4,5),List(1,2,3,4,5),  List(1,2,3,4,5))
val second: List[List[Int]] = List(List(1,2,3,4,5),List(1,23,3,45,5),List(1,2,3,4,5))

var diff: List[String] = List[String]()
for (i <- List.range(0, first.size)){
  for (j <- List.range(0, first(0).size)){
    println(first(i)(j) + " " + second(i)(j))
    if (first(i)(j) != second(i)(j)) diff = diff ::: (s"${second(i)(j)}" :: Nil)
  }
}

当然我不喜欢这个,我试图用理解来写一个解决方案,但没有成功 .

我能得到的最接近的是:

for {(lf,ls) <- (first zip second) } yield if (lf == ls) lf else ls

但是从理解中我无法生成与输入类型不同的String列表 .

有什么建议吗?

2 回答

  • 3

    惯用的Scala会是这样的:

    (
      for {
        (row1, row2) <- (first, second).zipped   // go through rows with the same index
        (value1, value2) <- (row1, row2).zipped  // go through values with the same indexes
        if value1 != value2                      // leave only different values in the list
      } yield value2.toString
    ).toList
    

    最好使用 zipped ,而不是 zip ,因为 zipped 不会在内存中产生整个压缩的 List .

    此外,由于类型推断的怪癖,最后你必须做 toList .

  • 0

    像这样的东西产生相同的结果

    val diff = for {
      firstInner <- first
      v1 <- firstInner
      secondInner <- second
      v2 <- secondInner
    } yield if (v1 != v2) s"$v2}"
    
    println(diff2 mkString ", ") // prints 23, 45
    

    但是,如果数组大小不同,则会导致IndexOutOfBoundsException失败 .

相关问题