我有一张地图m
val m = Map(1->2, 3->4, 5->6, 7->8, 4->4, 9->9, 10->12, 11->11)
现在我想要一个其键等于值的地图。所以我这样做
def eq(k: Int, v: Int) = if (k == v) Some(k->v) else None
m.flatMap((k,v) => eq(k,v))
这给了我错误
error: wrong number of parameters; expected = 1
m.flatMap((k,v) => eq(k,v))
上述代码有什么问题? flatMap
期望一个参数函数,这里我传递一个参数,它是一对整数。
这也有效
m.flatMap {
case (k,v) => eq(k,v)
}
但这不是
m.flatMap {
(k,v) => eq(k,v)
}
看起来我错过了一些东西。帮助
答案 0 :(得分:7)
没有这样的语法:
m.flatMap((k,v) => eq(k,v))
嗯,实际上有这样的语法,但实际上它用在接受两个参数的函数中(比如reduce):
List(1,2,3,4).reduce((acc, x) => acc + x)
m.flatMap {
case (k,v) => eq(k,v)
}
语法有效,因为实际上它是这样的:
val temp: PartialFunction[Tuple2[X,Y], Tuple2[Y,X]] = {
case (k,v) => eq(k,v) // using literal expression to construct function
}
m.flatMap(temp) // with braces ommited
这里关键的是case
字的用法(实际上,有一个讨论可以启用你的语法)which turns usual braces expression,就像{ ... }
一样,成为一个完整的匿名部分函数
答案 1 :(得分:6)
(如果你想简单地修复你得到的错误,请参阅第二个解决方案(使用flatMap
);如果你想要一个更好的解决方案,请从头开始阅读。)
您需要的是filter
而不是flatMap
:
def eq(k: Int, v: Int) = k == v
val m = Map(1->2, 3->4, 5->6, 7->8, 4->4, 9->9, 10->12, 11->11)
m.filter((eq _).tupled)
...当然只需要以下内容,而不需要eq
:
m.filter { case (k, v) => k == v }
<强>结果:强>
Map(9 -> 9, 11 -> 11, 4 -> 4)
或......如果您想坚持使用flatMap
首先,您必须知道flatMap
将传递给您的函数TUPLES而不是键和值作为单独的参数。
此外,您必须将Option
返回的eq
更改为可以flatMap
或List
等序列反馈给Map
的内容(实际上任何GenTraversableOnce
都是准确的):
def eq(k: Int, v: Int) = if (k == v) List(k -> v) else Nil
m.flatMap { case (k,v) => eq(k,v) } // use pattern matching to unpack the tuple
或丑陋但等同于:
m.flatMap { x => eq(x._1, x._2) }
或者,您可以将eq
转换为取代元组:
m.flatMap((eq _).tupled)
答案 2 :(得分:3)
我认为你想要的只是一个单一的论证,而不是两个论点。像这样的东西可能会起作用
m.flatMap(k => eq(k._1, k._2))
有效的代码段使用模式匹配。你给你夫妇的两个元素命名。它是一个部分功能,可以在你的flatMap中使用。
答案 3 :(得分:3)
你必须这样做:
m.flatMap { case (k,v) => eq(k,v) }
请注意,这里我切换到花括号,它表示一个功能块而不是参数,这里的函数是一个case语句。这意味着传递给flatMap
的功能块是 partialFunction ,仅对与case语句匹配的项目调用。
答案 4 :(得分:1)
您的eq
函数有两个参数,这就是您收到类型错误的原因。尝试:
def f(p: (Int, Int)) = if (p._1 == p._2) Some(p) else None
m flatMap f