patternModerate
Pair matching elements from two lists
Viewed 0 times
elementstwolistsfrompairmatching
Problem
Here is a method that takes two lists (
I spent way too much time writing this method, and it feels clumsy and complex, not scala idiomatic.
How could I have done this simpler? and could I make it faster?
l1 and l2) and pairs up elements that "match". As you can see at the end of the code block these lists consist of matching elements but in different indexes. The method pairUp outputs matching elements paired up, and discards those without a pair.I spent way too much time writing this method, and it feels clumsy and complex, not scala idiomatic.
How could I have done this simpler? and could I make it faster?
case class A(serial:Int) {
def matches(b:B):Boolean = this.serial == b.serial
}
case class B(serial:Int)
import scala.annotation.tailrec
@tailrec def pairUp(
list1:List[A],
list2:List[B],
i:Int=0,
pairs:List[(A, B)]=List.empty[(A,B)]
):List[(A,B)] = {
if (list1.isEmpty || list2.isEmpty) return pairs
else {
if (i == list2.length) // this list1 element has no match
return pairUp(
list1.tail, // so discard
list2,
0, // reset counter
pairs)
else {
if (list1.head matches list2.head) // these elements match
return pairUp(
list1.tail,
list2.tail,
0,
pairs :+ ((list1.head, list2.head)))
else
return pairUp(
list1,
list2.tail :+ list2.head, // list2 element to back
i + 1,
pairs)
}
}
}
val l1 = List(0, 1, 2, 3, 4, 5).map(A(_))
val l2 = List(1, 3, 0, 2, 4).map(B(_))
val pairs = pairUp(l1, l2)
// List((A(0),B(0)), (A(1),B(1)), (A(2),B(2)), (A(3),B(3)), (A(4),B(4)))
println(pairs)Solution
I am not an expert at scala, but this works for me
The for comprehension, takes each element of list1 and an element of list2 and yields a tuple only if the serial values match.
def pairUp2( list1: List[A], list2: List[B]): List[(A, B)] = {
(for{
a <- list1
b <- list2
if a.serial == b.serial
} yield (a,b))
}
val pairs = pairUp2(l1, l2)
pairs: List[(A, B)] = List((A(0),B(0)), (A(1),B(1)), (A(2),B(2)), (A(3),B(3)), (A(4),B(4)))The for comprehension, takes each element of list1 and an element of list2 and yields a tuple only if the serial values match.
Code Snippets
def pairUp2( list1: List[A], list2: List[B]): List[(A, B)] = {
(for{
a <- list1
b <- list2
if a.serial == b.serial
} yield (a,b))
}
val pairs = pairUp2(l1, l2)
pairs: List[(A, B)] = List((A(0),B(0)), (A(1),B(1)), (A(2),B(2)), (A(3),B(3)), (A(4),B(4)))Context
StackExchange Code Review Q#40297, answer score: 12
Revisions (0)
No revisions yet.