Scala - lambda参数可以匹配元组吗?

时间:2011-08-23 15:37:31

标签: scala

所以说我有一些像

这样的清单
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

val m = l.filter( (n, s) => n != 2 )

任何帮助将不胜感激 - 使用2.9.0.1

5 个答案:

答案 0 :(得分:78)

这是你能得到的最接近的地方:

 val m = l.filter { case (n, s) => n != 2 }

它基本上是匿名PartialFunction内的模式匹配语法。 tupled对象和特征中也有Function个方法,但它们只是这个模式匹配表达式的包装。

答案 1 :(得分:18)

嗯,虽然基普顿有一个很好的答案。你可以通过这样做来缩短它。

val l = List((1, "blue"), (5, "red"), (2, "green"))
val m = l.filter(_._1 != 2)

答案 2 :(得分:8)

有很多选择:

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

答案 3 :(得分:5)

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 )

答案 4 :(得分:0)

我思索过同样的问题,并于今天提出了你的问题。

我不太喜欢部分函数方法(任何具有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)

也许这证明是有用的。 {@ 1}}对象自然应放在某个工具命名空间中。

附录:

适用于您的案件:

unTuple