这是挑战(Scala 2.11):
(for (i <- -3 to 3) yield (f(i), i)).toMap
f():Int =&gt; Int是一个未知的参数,它被传递到我的代码中。生成的映射将是有界空间上函数的“逆”。
如果
,这将正常工作f(i: Int) = i * 2
但如果
, NOT 工作正常f(i: Int) = i * i
因为,例如f(-2)= 4和f(2)= 4这使得重复键和第二个覆盖第一个
我的问题是:当有重复的键时,我怎么能抛出IllegalArgumentException ...(即告诉用户他/她的功能在有界空间内不是“可逆的”)
我知道我可以使用mutable.Map并编写一个循环,而不是用于理解(例如使用尾递归),它在每次迭代时执行“map.get”并且如果已经存在,则抛出... 。,否则加入地图。
有不可改变的方法吗?
对于额外的积分,我还需要检查f(i)是否在界限内(-3..3)并忽略如果不是......
答案 0 :(得分:1)
我想你可以在你的范围内弃左,而不是用于理解,例如:
(-3 to 3).foldLeft(Map.empty[Int, Int]){ case (result, next) =>
val answer = f(next)
result.get(answer).fold(result + answer -> next)(_ => throw new IllegalArgumentException)
}
我没有仔细检查所有使用的类的API,因此代码可能不会编译,但类似的东西应该。
答案 1 :(得分:1)
将其分解为更小的步骤,很明显for-comprehension返回一个向量。 toMap
是创建地图的原因。但是,在您的方案中,foldLeft
比toMap
更合适。
val f = (i:Int) => i * i
val pairs = for (i <- -3 to 3) yield f(i) -> i
val result = pairs.foldLeft(Map.empty[Int, Int]) { case (map, (k, v)) =>
if(map contains k)
map //or throw IllegalArgumentException here
else
map + (k -> v)
}
println(result)
这里有更多的步骤(但功能完全相同)答案:
val f = (i:Int) => i * i
val pairs = for (i <- -3 to 3) yield f(i) -> i
val zero = Map.empty[Int, Int]
def putIfAbsent(map:Map[Int, Int], pair:(Int, Int)):Map[Int, Int] =
pair match { case (k, v) =>
if(map contains k)
map
else
map + (k -> v)
}
val result = pairs.foldLeft(zero)(putIfAbsent)
println(result)