Reputation: 72
I am trying to write idiomatic scala code to loop through two lists of lists, and to generate a new list containing only the differences of the two lists.
In procedural Scala I would do something like this:
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)
}
}
Of course I do not like this, I have attempted to write a solution using for comprehension, but without success.
The closest thing I could get to was this:
for {(lf,ls) <- (first zip second) } yield if (lf == ls) lf else ls
but from that for comprehension I can not generate a list of String being of a different type from the input one.
Any suggestion?
Upvotes: 2
Views: 1330
Reputation: 14224
The idiomatic Scala would be something like this:
(
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
It's better to use zipped
, than zip
here, because zipped
doesn't produce the whole zipped List
in memory.
Also, you have to do toList
in the end, due to a quirk in type inference.
Upvotes: 3
Reputation: 604
Something like this produces the same results
val diff = for {
firstInner <- first
v1 <- firstInner
secondInner <- second
v2 <- secondInner
} yield if (v1 != v2) s"$v2}"
println(diff2 mkString ", ") // prints 23, 45
But this ofcourse fails with IndexOutOfBoundsException if the array sizes isn't of the same size.
Upvotes: 0