Scala - lambda 参数可以匹配元组吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7163676/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Scala - can a lambda parameter match a tuple?
提问by dvmlls
So say i have some list like
所以说我有一些清单
val l = List((1, "blue"), (5, "red"), (2, "green"))
And then i want to filter one of them out, i can do something like
然后我想过滤掉其中一个,我可以做类似的事情
val m = l.filter(item => {
val (n, s) = item // "unpack" the tuple here
n != 2
}
Is there any way i can "unpack" the tuple as the parameter to the lambda directly, instead of having this intermediate itemvariable?
有什么办法可以直接将元组“解包”为 lambda 的参数,而不是使用这个中间item变量?
Something like the following would be ideal, but eclipse tells me wrong number of parameters; expected=1
像下面这样的东西是理想的,但日食告诉我 wrong number of parameters; expected=1
val m = l.filter( (n, s) => n != 2 )
Any help would be appreciated - using 2.9.0.1
任何帮助将不胜感激 - 使用 2.9.0.1
回答by Kipton Barros
This is about the closest you can get:
这是你能得到的最接近的:
val m = l.filter { case (n, s) => n != 2 }
It's basically pattern matching syntax inside an anonymous PartialFunction. There are also the tupledmethods in Functionobject and traits, but they are just a wrapper around this pattern matching expression.
它基本上是匿名PartialFunction 中的模式匹配语法。tupled在Functionobject 和 traits中也有方法,但它们只是这个模式匹配表达式的包装器。
回答by Amir Raminfar
Hmm although Kipton has a good answer. You can actually make this shorter by doing.
嗯,虽然基普顿有一个很好的答案。你实际上可以通过这样做来缩短它。
val l = List((1, "blue"), (5, "red"), (2, "green"))
val m = l.filter(_._1 != 2)
回答by Rex Kerr
There are a bunch of options:
有很多选择:
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
回答by comonad
val m = l.filter( (n, s) => n != 2 )
... is a type mismatch because that lambda defines a
... 是类型不匹配,因为 lambda 定义了一个
Function2[String,Int,Boolean]with two parameters instead ofFunction1[(String,Int),Boolean]with oneTuple2[String,Int]as its parameter.
Function2[String,Int,Boolean]用两个参数代替Function1[(String,Int),Boolean]以一Tuple2[String,Int]为参数。
You can convert between them like this:
您可以像这样在它们之间进行转换:
val m = l.filter( ((n, s) => n != 2).tupled )
回答by akauppi
I've pondered the same, and came to your question today.
我也是这么想的,今天来回答你的问题。
I'm not very fond of the partial function approaches (anything having case) since they imply that there could be more entry points for the logic flow. At least to me, they tend to blur the intention of the code. On the other hand, I really do want to go straight to the tuple fields, like you.
我不是很喜欢部分函数方法(任何有case),因为它们暗示逻辑流可能有更多的入口点。至少对我来说,他们倾向于模糊代码的意图。另一方面,我真的很想像你一样直接进入元组字段。
Here's a solution I drafted today. It seems to work, but I haven't tried it in production, yet.
这是我今天起草的解决方案。它似乎有效,但我还没有在生产中尝试过。
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)
)
Output:
输出:
(a,1)
(b,2)
(a,1,true)
(b,2,false)
Maybe this turns out to be useful. The unTupleobject should naturally be put aside in some tool namespace.
也许结果证明这很有用。该unTuple对象自然应该放在某个工具命名空间中。
Addendum:
附录:
Applied to your case:
适用于您的案例:
val m = l.filter( unTuple( (n:Int,color:String) =>
n != 2
))

