【问题标题】:Map both keys and values of a Scala Map映射 Scala Map 的键和值
【发布时间】:2012-02-26 04:08:05
【问题描述】:

Scala 的 MapLike trait 有一个方法

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

但我有时想要不同的类型:

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

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

【问题讨论】:

    标签: scala


    【解决方案1】:

    map 方法遍历所有 (key, value) 对。你可以这样使用它:

    val m = Map("a" -> 1, "b" -> 2)
    
    val incM = m map {case (key, value) => (key, value + 1)}
    

    【讨论】:

    • 如果你已经有函数f : (A,B) => (A,C),那么你可以简单地m.map(f.tupled)。与val f = (x: String, y: Int) => (x, y+1) 一起工作,但奇怪的是,如果我将f 等同于def 定义,repl 会抱怨。
    • 关键字case在这里实现了什么?
    • @Omnipresent {case (key, value) => ...} 在这种情况下只是一个模式匹配。我没有给map 提供函数,而是给它一个部分函数。
    • 注意:case 将允许您将类型放入它的模式中,但这并不安全,因为它可能会产生运行时错误(因为它只是模式匹配)。同时,如果您更改了map 函数下的集合结构,导致无法解释为(key, value) 的对象太少或太多,那么我希望您再次遇到运行时错误。 :(
    【解决方案2】:

    这段代码怎么样:

    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
    )
    

    【讨论】:

    【解决方案3】:

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

    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)
    

    代码未经测试,但它应该以某种类似的方式工作。

    【讨论】:

      【解决方案4】:

      使用一些 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 的解决方案。

      【讨论】:

        【解决方案5】:
        m map (t => (t._1, t._2 + 1))
        
        m map (t => t._1 -> t._2 + 1)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2022-01-26
          • 2011-06-14
          • 2013-02-02
          • 2018-09-25
          • 2018-07-23
          • 1970-01-01
          • 1970-01-01
          • 2015-09-14
          相关资源
          最近更新 更多