'Convert function that works with List[Int] to take Seq[Int]
I've been provided with a solution on another question that works with List[Int] to get the indices at which two lists intersect.
@tailrec
def indicesOfIntersection(left: List[Int], right: List[Int], lidx: Int = 0, ridx: Int = 0, result: List[(Int, Int)] = Nil): List[(Int, Int)] = (left, right) match {
case (Nil, _) | (_, Nil) => result.reverse
case (l::tail, r::_) if l < r => indicesOfIntersection(tail, right, lidx+1, ridx, result)
case (l::_, r::tail) if l > r => indicesOfIntersection(left, tail, lidx, ridx+1, result)
case (l::ltail, r::rtail) => indicesOfIntersection(ltail, rtail, lidx+1, ridx+1, (lidx, ridx) :: result)
}
And am hoping to convert it to one that works directly on Arrays, without doing anything inefficient (because it is used on big arrays)
The advice I got was
Yeah
Nilandhead::tailextractors only work for lists. You can trivially rewrite it for anyseq: just replaceNilwithSeq()andhead::tailwithhead+:tail
Unfortunately, the trivial is still over my head and I require a bit more spoon feeding :)
I took a stab with the following which passed compile-time checks, but fails at runtime:
@tailrec
def indicesOfIntersection(left: Seq[Int], right: Seq[Int], lidx: Int = 0, ridx: Int = 0, result: Seq[(Int, Int)] = Seq()): Seq[(Int, Int)] = (left, right) match {
case (l::tail, r::_) if l < r => indicesOfIntersection(tail, right, lidx+1, ridx, result)
case (l::_, r::tail) if l > r => indicesOfIntersection(left, tail, lidx, ridx+1, result)
case (l::ltail, r::rtail) => indicesOfIntersection(ltail, rtail, lidx+1, ridx+1, (lidx, ridx) +: result)
case (Seq(), _) | (_, Seq()) => result.reverse
}
scala.MatchError: (WrappedArray(19, 68, 419...
(error truncated due to essentially being a dump of my first array input)
Thanks in advance for pointing out what I've done wrong.
Update
I've gotten a little further by updating all instances of :: operators in the case statements to +: as well (although I don't understand the syntax, thinking this was just a place for destructuring).
It's running now, but I'm unsure if it's "correct" - specifically it seems that if the final case (formerly the first case) is comparing empty Seq() instances, they won't necessarily be considered equal just because the are both empty (unlike the former Nil comparison)?
Update
I've been informed in the comments that one cannot simply use tail on Arrays without incurring a heavy cost (presumably traversing the entire array?) so I'm still looking for a solution which replaces these nuances with something that is equally performant for Arrays (or any Seq, if you wish)
Solution 1:[1]
Try wrapping your Array using scala.collection.immutable.ArraySeq.unsafeWrapArray and then converting it to a View using .view.
Making it a View will allow you to take the tail without actually copying the underlying array.
See also https://docs.scala-lang.org/overviews/collections-2.13/views.html
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | kag0 |
