我希望创建一个按名称键入的Map,其中包含具有该名称的事物的数量。我有一个名称的东西列表,其中可能包含多个具有相同名称的项目。像这样编码我得到一个错误“类型不匹配;找到:字符串必需:(String,Int)”:
//variation 0, produces error
(Map[String, Int]() /: entries)((r, c) => { r + (c.name, if (r.contains(c.name)) (c.name) + 1 else 1) })
这让我感到困惑,因为我虽然(a,b)是Tuple2,因此适合与Map add一起使用。以下任一变体均按预期工作:
//variation 1, works
(Map[String, Int]() /: entries)((r, c) => { r + Tuple2(c.name, if (r.contains(c.name)) (c.name) + 1 else 1) })
//variation 2, works
(Map[String, Int]() /: entries)((r, c) => {
val e = (c.name, if (r.contains(c.name)) (c.name) + 1 else 1) })
r + e
我不清楚我的第一个版本出现问题的原因;任何人都可以建议。我使用Scala-IDE 2.0.0 beta 2编辑源代码;错误来自Eclipse Problems窗口。
答案 0 :(得分:3)
将单个元组参数传递给与运算符表示法一起使用的方法(如+
方法)时,应使用双括号:
(Map[String, Int]() /: entries)((r, c) => { r + ((c.name, r.get(c.name).map(_ + 1).getOrElse(1) )) })
我也改变了Int
的计算,这在你的例子中看起来很有趣......
答案 1 :(得分:3)
因为+
用于将字符串连接到字符串。在这种情况下,括号不是指元组,而是指参数。
Scala已将+
用于其他内容,这会导致各种问题,就像您提到的那样。
将+
替换为updated
,或使用->
代替,
。
答案 2 :(得分:1)
r + (c.name, if (r.contains(c.name)) (c.name) + 1 else 1)
被解析为
r.+(c.name, if (r.contains(c.name)) (c.name) + 1 else 1)
因此,编译器会在+
上查找带有2个参数的Map
方法,但找不到它。我更喜欢双括号的形式(如Jean-Philippe Pellet建议的那样)
r + (c.name -> if (r.contains(c.name)) (c.name) + 1 else 1)
更新:
如果Pellet是正确的,最好写
r + (c.name -> r.getOrElse(c.name, 0) + 1)
(当然,詹姆斯·伊里的解决方案表达了同样的意图)。