Does Scala allow for this kind of extractor?
Let's say I have this collection:
val a = Array(Array(1,2,3,4,5),Array(4,5),Array(5),Array(1,2,6,7,8))
Is there a way to define an extractor which would work in the following way:
a.foreach(e => {
e match {
case Array( ending with 5 ) =>
case _ =>
}
})
Sorry for the pseudocode, but I don't know how to express it. Is there a way to match something having 5 as the last element? What if I would want to match something having a 1 as the first element and a 5 as the last? Could this work for arrays of various lengths ( note that I specifically chose different lengths for my arrays in the开发者_Python百科 example ).
Thanks!
Yes you can:
object EndsWith {
def unapply[A]( xs: Array[A] ) =
if( xs.nonEmpty ) Some( xs.last ) else None
}
On your example:
val a = Array(Array(1,2,3,4,5),Array(4,5),Array(5),Array(1,2,6,7,8))
a foreach {
case e @ EndsWith(5) => println( e.mkString("(",",",")" ) )
case _ =>
}
It prints as expected (1,2,3,4,5)
, (4,5)
and (5)
With the same approach, you could write an extractor StartWith
and then add a method to combine them in a new extractor matching both conditions.
a.foreach(e => {
e match {
case a: Array[Int] if a.last == 5 =>
case _ =>
}
})
You can do something a little better for matching on the first elements:
a.foreach(e => {
e match {
case Array(1, _*) =>
case _ =>
}
})
Unfortunately the @_*
thing has to be the last item in the list of array arguments. But you can make the matching before that as complex as you want.
scala> val Array(1, x @_*) = Array(1,2,3,4,5)
x: Seq[Int] = Vector(2, 3, 4, 5)
scala> val Array(1, b, 3, x @_*) = Array(1,2,3,4,5)
b: Int = 2
x: Seq[Int] = Vector(4, 5)
The case
syntax supports if
s, so this would work:
a foreach {
case a: Array[Int] if a.last == 5 =>
case _ =>
}
a.foreach (ar => ar.last match {
case 5 => println ("-> 5] " + ar.mkString ("~"))
case _ => println (" ?] " + ar.mkString (":")) })
Why don't you match directly for the last element?
-> 5] 1~2~3~4~5
-> 5] 4~5
-> 5] 5
?] 1:2:6:7:8
精彩评论