2011-07-15 16 views
5

比方说,我有这样的集合:斯卡拉是否允许这种提取器?

val a = Array(Array(1,2,3,4,5),Array(4,5),Array(5),Array(1,2,6,7,8)) 

有没有办法来定义一个提取器,其将在以下方式工作:

a.foreach(e => { 
    e match { 
     case Array(ending with 5) => 
     case _ => 
    } 
}) 

很抱歉的伪代码,但我不知道如何表达它。有没有办法匹配5个作为最后一个元素的东西?如果我想匹配1作为第一个元素和5作为最后一个元素的东西呢?这可以适用于各种长度的数组(请注意,我特意为示例中的数组选择了不同的长度)。

谢谢!

+3

,这是非常密切的关系:http://stackoverflow.com/questions/6697645/scala-get-first-and-last-elements-of-list-using-pattern-matching –

+0

尽量避免解构数组超过提取器,它们被循环/复制到Seq并具有O(n)复杂性。 – lisak

回答

9
a.foreach(e => { 
    e match { 
     case a: Array[Int] if a.last == 5 => 
     case _ => 
    } 
}) 

你可以做的东西好一点,对第一要素匹配:

a.foreach(e => { 
    e match { 
     case Array(1, _*) => 
     case _ => 
    } 
}) 

不幸的是,@_*事情必须是在阵列参数列表的最后一个项目。但是,您可以在此之前进行匹配,尽可能复杂。

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) 
+1

将'_ *'绑定到'x'有什么意义?更是如此,为'_'? –

+0

@ Jean-Philippe Pellet:海报没有说明阵列内容是否真的需要。如果需要它们,然后将它们绑定到一个变量允许您使用它们。 – dhg

+0

@ Jean-Philippe Pellet:尽管对'_'好,我不知道你可以自己做'_ *'。谢谢。 – dhg

4

case语法支持if S,所以这会工作:

a foreach { 
    case a: Array[Int] if a.last == 5 => 
    case _ => 
} 
11

是的,你可以:

object EndsWith { 
    def unapply[A](xs: Array[A]) = 
    if(xs.nonEmpty) Some(xs.last) else None 
} 

在您的例子:

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 _ => 
} 

它打印一个小号预期(1,2,3,4,5)(4,5)(5)

用同样的方法,你可以写一个提取StartWith,然后添加一个方法给他们一个新的提取符合两个条件结合起来。

+0

这就是提取器的做法。 – jilen

1
a.foreach (ar => ar.last match {      
    case 5 => println ("-> 5] " + ar.mkString ("~")) 
    case _ => println (" ?] " + ar.mkString (":")) }) 

为什么不直接匹配最后一个元素?

-> 5] 1~2~3~4~5 
-> 5] 4~5 
-> 5] 5 
    ?] 1:2:6:7:8