Scala强调地图和过滤器的表示法

时间:2018-03-05 05:56:46

标签: scala

说我有以下代码:

val a: List[(Int, String)] = List((1,"A"),(2,"B"),(3,"C"))
val b: List[String] = List("A","C","E")

我能做到:

a.map{case (fst,snd) => (fst,snd + "a")}
a.filter{case (_,snd) => b.contains(snd)}

但为什么我不能这样做:

a.map((_._1,_._2 + "a"))
a.filter(b.contains(_._2))

有没有办法用下划线表示法完成此操作,还是我被迫在这里?

2 个答案:

答案 0 :(得分:5)

例如:

openssl req -x509 -newkey rsa:4096 -nodes -out cert.pem -keyout key.pem -days 365

每个占位符(即每个下划线/ a.map((_._1,_._2 + "a")) )在参数表达式中引入新参数

To cite the Scala spec

  

表达式(句法类别_)   可以在标识符的位置包含嵌入的下划线符号Expr   是合法的。这样的表达式表示随后的匿名函数   下划线的出现表示连续的参数。

     

[...]

     

左列中的匿名函数使用占位符   句法。这些中的每一个都相当于其右侧的匿名函数。

_

当您需要多次使用给定参数时,您必须使用展开的表单。因此,您的示例必须重写为:

|---------------------------|----------------------------|
|`_ + 1`                    | `x => x + 1`               |
|`_ * _`                    | `(x1, x2) => x1 * x2`      |
|`(_: Int) * 2`             | `(x: Int) => (x: Int) * 2` |
|`if (_) x else y`          | `z => if (z) x else y`     |
|`_.map(f)`                 | `x => x.map(f)`            |
|`_.map(_ + 1)`             | `x => x.map(y => y + 1)`   |

例如

a.map(x => (x._1, x._2 + "a"))

问题在于您实际上是将匿名函数传递给a.filter(b.contains(_._2)) 而不是contains,因此您无法在此处使用下划线表示法。相反,你必须写

filter

答案 1 :(得分:2)

你无法做到

a.map((_._1,_._2 + "a"))

因为_将匹配每次迭代的 iterable 的元素。第一个_将匹配第一个可迭代的元素,第二个_将匹配第二个可迭代的元素,依此类推。 _._ 1将匹配第一个可迭代元组元素的第一个元素,但_._ 2将尝试获取第二个可迭代的tupled elements的第二个元素。 由于没有第二个可迭代,Scala编译器会抛出编译错误

在你的第二行代码中

a.filter(b.contains(_._2))

_._2尝试获取b的tupled iterable的第二个元素,但b不是tupled iterable。 b只是 String 的可迭代。

让它可以工作

a.map(x => (x._1, x._2 + "a"))
a.filter(x => b.contains(x._2))
相关问题