斯卡拉 – 一个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直接,而不是有这个中间itemvariables?

类似下面的东西会是理想的,但日食告诉我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 ))