rle*_*ndi 4 arrays functional-programming scala pattern-matching variable-assignment
我有这样的输入:"1 2 3 4 5".
我想做的是创建一组新变量,让a它们成为序列中的第一个,b第二个,xs其余作为序列(显然我可以在3个不同的行中完成,但我想使用多个任务).
一些搜索帮助我找到了正确忽略的序列模式,我可以使用它:
val Array(a, b, xs @ _*) = "1 2 3 4 5".split(" ")
Run Code Online (Sandbox Code Playgroud)
我不明白的是,如果我用元组尝试它,为什么它不起作用?我收到一个错误:
val (a, b, xs @ _*) = "1 2 3 4 5".split(" ")
Run Code Online (Sandbox Code Playgroud)
错误消息是:
<console>:1: error: illegal start of simple pattern
Run Code Online (Sandbox Code Playgroud)
有没有使用多任务的替代方案Array?
我几天前刚开始玩Scala,所以请耐心等待:-)在此先感谢!
Rex*_*err 15
其他答案告诉你为什么你不能使用元组,但数组为此目的很尴尬.我更喜欢列表:
val a :: b :: xs = "1 2 3 4 5".split(" ").toList
Run Code Online (Sandbox Code Playgroud)
dhg*_*dhg 11
val Array(a, b, xs @ _*) = "1 2 3 4 5".split(" ")
Run Code Online (Sandbox Code Playgroud)
您在这里看到的语法是一个简单的模式匹配.它的工作原理是因为"1 2 3 4 5".split(" ")评估为Array:
scala> "1 2 3 4 5".split(" ")
res0: Array[java.lang.String] = Array(1, 2, 3, 4, 5)
Run Code Online (Sandbox Code Playgroud)
由于右手边是a Array,左手尺寸上的图案也必须是aArray
只有当右手大小评估为元组时,左侧才可以是元组:
val (a, b, xs) = (1, 2, Seq(3,4,5))
Run Code Online (Sandbox Code Playgroud)
从技术上讲,这里发生的是模式匹配语法是unapply在Array对象上调用方法,如下所示:
def unapplySeq[T](x: Array[T]): Option[IndexedSeq[T]] =
if (x == null) None else Some(x.toIndexedSeq)
Run Code Online (Sandbox Code Playgroud)
请注意,该方法接受Array.这就是Scala必须在赋值的右手大小上看到的内容.它返回一个Seq,允许@_*您使用的语法.
你的元组版本不起作用,因为用Tuple3s 作为参数unapplySeq来定义Product3,而不是Array:
def unapply[T1, T2, T3](x: Product3[T1, T2, T3]): Option[Product3[T1, T2, T3]] =
Some(x)
Run Code Online (Sandbox Code Playgroud)
你可以实际上像这样"提取器",通过简单地创建一个对象和编写一个unapply或一个unapplySeq方法来做任何你想做的事情.
答案是:
val a :: b :: c = "1 2 3 4 5".split(" ").toList
Run Code Online (Sandbox Code Playgroud)
应该澄清,在某些情况下,可能只想绑定列表中的前n个元素,忽略不匹配的元素.要做到这一点,只需添加一个尾随下划线:
val a :: b :: c :: _ = "1 2 3 4 5".split(" ").toList
Run Code Online (Sandbox Code Playgroud)
那样:
c = "3" vs. c = List("3","4","5")
Run Code Online (Sandbox Code Playgroud)