映射Scala映射的键和值

映射Scala映射的键和值,scala,Scala,Scala的MapLiketrait有一个方法 mapValues [C] (f: (B) ⇒ C): Map[A, C] 但有时我想要一种不同的类型: mapKeysAndValues [C] (f: (A, B) ⇒ C): Map[A, C] 有没有一个简单的方法来做到这一点,我错过了?当然,这可以通过折叠来完成。map方法迭代所有(键、值)对。您可以这样使用它: val m = Map("a" -> 1, "b" -> 2) val incM = m map {ca

Scala的
MapLike
trait有一个方法

mapValues [C] (f: (B) ⇒ C): Map[A, C] 
但有时我想要一种不同的类型:

mapKeysAndValues [C] (f: (A, B) ⇒ C): Map[A, C] 

有没有一个简单的方法来做到这一点,我错过了?当然,这可以通过折叠来完成。

map
方法迭代所有
(键、值)
对。您可以这样使用它:

val m = Map("a" -> 1, "b" -> 2)

val incM = m map {case (key, value) => (key, value + 1)}
那么这个代码呢:

val m = Map(1 -> "one", 2 -> "two")
def f(k: Int, v: String) = k + "-" + v
m map {case (k, v) => (k, f(k, v))}
产生:

 Map(1 -> 1-one, 2 -> 2-two)
这可以打包为实用方法:

def mapKeysAndValues[A,B,C](input: Map[A,B], fun: (A, B) => C) = 
  input map {case(k,v) => (k, fun(k, v))}
用法:

mapKeysAndValues(
  Map(1 -> "one", 2 -> "two"), 
  (k: Int, v: String) => k + "-" + v
)

您可以创建一个实用程序类:

class MyMapLike[K,V](m:MapLike[K,V,_]){
 def mapKeysAndValues[R](f: (K, V) => R)={
   m.map{case (k,v)=> f(k,v)}
 } 
}
object MyMapLike{
 implicit def maplike2mymaplike[K,V](ml:MapLike[K,V,_]):MyMapLike[K,V]=new MyMapLike(m)

}

import MyMapLike._
Map(1 -> "one", 2 -> "two").mapKeysAndValues(k,v=>v*k)
代码未经测试,但应以类似的方式工作。

使用一些Scalaz:

scala> def fst[A, B] = (x: (A, B)) => x._1
fst: [A, B]=> (A, B) => A

scala> Map(1 -> "Lorem", 2 -> "Ipsum").map(fst &&& Function.tupled(_.toString + _))
res1: scala.collection.immutable.Map[Int,java.lang.String] = Map(1 -> 1Lorem, 2 -> 2Ipsum)

我更喜欢@tenshi的解决方案。

如果你已经有了一个函数
f:(a,B)=>(a,C)
,那么你可以简单地
m.map(f.tuple)
。使用
val f=(x:String,y:Int)=>(x,y+1)
但是奇怪的是,如果我用
def
等价地定义
f
,repl会抱怨。关键字
case
在这里实现了什么?@Omnipresent
{case(key,value)=>…}
在这种情况下只是一个模式匹配。我没有为
映射提供函数,而是为它提供了一个部分函数。注意:
case
将允许您将类型放入它的模式中,但这并不安全,因为它可能会创建运行时错误(因为它只是一个模式匹配)。同时,如果您更改
map
函数下集合的结构,使对象太少或太多而无法解释为
(键、值)
,那么我希望您再次遇到运行时错误:(这不是和你的一样吗?
m map (t => (t._1, t._2 + 1))

m map (t => t._1 -> t._2 + 1)