[英]Scala - can a lambda parameter match a tuple?
所以说我有一些像这样的清单
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
变量?
像下面这样的东西是理想的,但是eclipse告诉我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
方法,但它们只是这个模式匹配表达式的包装器。
嗯,虽然基普顿有一个很好的答案。 你可以通过这样做来缩短它。
val l = List((1, "blue"), (5, "red"), (2, "green"))
val m = l.filter(_._1 != 2)
有很多选择:
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 )
...是一种类型不匹配,因为lambda定义了一个
Function2[String,Int,Boolean]
有两个参数而不是 Function1[(String,Int),Boolean]
,其中一个Tuple2[String,Int]
作为参数。 您可以像这样在它们之间进行转换:
val m = l.filter( ((n, s) => n != 2).tupled )
我一直在思考,今天就提出了你的问题。
我不太喜欢部分函数方法(任何有case
东西)因为它们暗示逻辑流可能有更多的入口点。 至少在我看来,它们往往模糊了代码的意图。 另一方面,我真的想直接去像你这样的元组字段。
这是我今天起草的解决方案。 它似乎有效,但我还没有在生产中尝试过它。
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
))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.