scala中非元组的多重赋值
Posted
技术标签:
【中文标题】scala中非元组的多重赋值【英文标题】:Multiple assignment of non-tuples in scala 【发布时间】:2011-01-23 19:28:24 【问题描述】:澄清一下,当我说多重赋值、并行赋值、解构绑定时,我指的是以下模式匹配 gem
scala> val (x,y) = Tuple2("one",1)
x: java.lang.String = one
y: Int = 1
将"one"
分配给x
,将1
分配给y
。
我正在尝试做
val (x,y) = "a b".split()
我期待 scala 会尝试将数组与模式匹配,如果数组的长度与模式的长度不匹配,则会抛出运行时异常。
我所有将Array
轻松转换为Tuple2
的尝试都是徒劳的。
scala> Tuple2(Array(1,2):_*)
<console>:7: error: wrong number of arguments for method apply: (T1,T2)(T1, T2)
in object Tuple2
Tuple2(Array(1,2):_*)
^
scala> Tuple2(Array(1,2).toList:_*)
<console>:7: error: wrong number of arguments for method apply: (T1,T2)(T1, T2)
in object Tuple2
Tuple2(Array(1,2).toList:_*)
有没有什么巧妙的方法可以对数组或列表使用多重赋值?
【问题讨论】:
【参考方案1】:您需要做的就是使您的 val 端(=
的左侧)与您的初始化程序(=
的右侧)兼容:
scala> val Array(x, y, z) = "XXX,YYY,ZZZ".split(",")
x: java.lang.String = XXX
y: java.lang.String = YYY
z: java.lang.String = ZZZ
如您所料,如果数组大小不匹配(在上面的示例中不是 3),则会在运行时抛出 scala.MatchError
。
【讨论】:
之所以有效,是因为对象Array
包含unapplySeq
方法,使其可用作提取器模式。调用Array.unapplySeq("XXX,YYY,ZZZ".split(",")
,返回Some(ArrayBuffer(XXX, YYY, ZZZ))
,这是一个Some
,并包含三个要绑定到x
、y
和z
的元素。
为什么val Array(X, Y, Z) = "XXX,YYY,ZZZ".split(",")
不起作用?我得到<console>:14: error: not found: value X...
@Batato 匹配变量必须小写【参考方案2】:
scala> val Array(x, y, _*) = "a b" 拆分 ""
x: java.lang.String = a
y: java.lang.String = b
【讨论】:
【参考方案3】:由于您的字符串可以包含任意内容,因此类型系统不能保证结果具有 2 元组形式(并且根本没有任何转换意义)。因此,无论如何您都必须处理序列(如数组)。
谢天谢地,有right-ignoring sequence patterns 可以让您方便地匹配结果值。
val Seq(x, y, _ @ _*) = "a b".split(" ")
【讨论】:
引用我自己的话:“我期待 scala 会尝试将数组与模式匹配,如果数组的长度与模式的长度不匹配,则会抛出运行时异常” ,另见兰德尔的解决方案。无论如何,这也是一个不错的选择。如此简单,我希望我自己考虑一下。 +1。 在 Scala 2.8 中,Array 不再是 Seq,因此该技术在此行不通。 该技术确实有效,您只需编写“Array”而不是“Seq”。或者,如果您对字符串的结尾感到冷漠, val Array(x, y) = "a b" split " " take 2val Array(x, y, _*) = "a b".split(" ")
也可以减少语法混乱。我不认为_ @
有用。以上是关于scala中非元组的多重赋值的主要内容,如果未能解决你的问题,请参考以下文章