Scala中的多个赋值而不使用Array?

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)

更复杂的答案

从技术上讲,这里发生的是模式匹配语法是unapplyArray对象上调用方法,如下所示:

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方法来做任何你想做的事情.


vir*_*yes 6

答案是:

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)