说我有以下代码:
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))
有没有办法用下划线表示法完成此操作,还是我被迫在这里?
答案 0 :(得分:5)
例如:
openssl req -x509 -newkey rsa:4096 -nodes -out cert.pem -keyout key.pem -days 365
每个占位符(即每个下划线/ a.map((_._1,_._2 + "a"))
)在参数表达式中引入新参数。
表达式(句法类别
_
) 可以在标识符的位置包含嵌入的下划线符号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))