斯卡拉 – 一个lambda参数可以匹配一个元组?
所以说,我有一些像列表
val l = List((1, "blue"), (5, "red"), (2, "green"))
然后我想过滤其中的一个,我可以做一些像
val m = l.filter(item => { val (n, s) = item // "unpack" the tuple here n != 2 }
有什么办法,我可以“解压”作为参数的lambda直接,而不是有这个中间item
variables?
类似下面的东西会是理想的,但日食告诉我wrong number of parameters; expected=1
wrong number of parameters; expected=1
val m = l.filter( (n, s) => n != 2 )
任何帮助将不胜感激 – 使用2.9.0.1
这是最接近你可以得到:
val m = l.filter { case (n, s) => n != 2 }
它基本上是匿名PartialFunction中的模式匹配语法。 Function
对象和traits中也有tupled
方法,但它们只是这个模式匹配expression式的一个包装。
嗯,虽然基普顿有一个很好的答案。 实际上你可以做得更短。
val l = List((1, "blue"), (5, "red"), (2, "green")) val m = l.filter(_._1 != 2)
有一堆select:
for (x <- l; (n,s) = x if (n != 2)) yield x l.collect{ case x @ (n,s) if (n != 2) => x } l.filter{ case (n,s) => n != 2 } l.unzip.zipped.map((n,s) => n != 2).zip // Complains that zip is deprecated
val m = l.filter( (n, s) => n != 2 )
…是一种types不匹配,因为lambda定义了一个
-
Function2[String,Int,Boolean]
用两个参数代替 -
Function1[(String,Int),Boolean]
以一个Tuple2[String,Int]
作为参数。
你可以像这样在它们之间进行转换:
val m = l.filter( ((n, s) => n != 2).tupled )
我也在思考这个问题,今天就提出你的问题。
我不喜欢部分函数方法(任何有case
),因为它们暗示逻辑stream可能有更多的入口点。 至less对我来说,他们倾向于模糊代码的意图。 另一方面,我真的很想直接进入像你这样的tuple字段。
这是我今天起草的解决scheme。 它似乎工作,但我还没有在生产中尝试过。
object unTuple { def apply[A, B, X](f: (A, B) => X): (Tuple2[A, B] => X) = { (t: Tuple2[A, B]) => f(t._1, t._2) } def apply[A, B, C, X](f: (A, B, C) => X): (Tuple3[A, B, C] => X) = { (t: Tuple3[A, B, C]) => f(t._1, t._2, t._3) } //... } val list = List( ("a",1), ("b",2) ) val list2 = List( ("a",1,true), ("b",2,false) ) list foreach unTuple( (k: String, v: Int) => println(k, v) ) list2 foreach unTuple( (k: String, v: Int, b: Boolean) => println(k, v, b) )
输出:
(a,1) (b,2) (a,1,true) (b,2,false)
也许这是有用的。 unTuple
对象自然应该放在一些工具名称空间中。
附录:
适用于你的情况:
val m = l.filter( unTuple( (n:Int,color:String) => n != 2 ))