通用地图上的Scala模式匹配

时间:2013-12-16 08:53:07

标签: scala generics

在Scala中进行模式匹配时,处理泛型和擦除的最佳方法是什么(在我的情况下是一个Map)。我正在寻找一个没有编译器警告的正确实现。我有一个函数,我想从中返回Map [Int,Seq [String]]。目前代码如下:

def teams: Map[Int, Seq[String]] = {
    val dateam = new scala.collection.mutable.HashMap[Int, Seq[String]]

    // data.attributes is Map[String, Object] returned from JSON parsing (jackson-module-scala)
    val teamz = data.attributes.get("team_players")
    if (teamz.isDefined) {
      val x = teamz.get
      try {
        x match {
          case m: mutable.Map[_, _] => {
            m.foreach( kv => {
              kv._1 match {
                case teamId: String => {
                  kv._2 match {
                    case team: Seq[_] => {
                      val tid: Int = teamId.toInt
                      dateam.put(tid, team.map(s => s.toString))
                    }
                  }
                }
              }
            })
          }
        }
      } catch {
        case e: Exception => {
          logger.error("Unable to convert the team_players (%s) attribute.".format(x), e)
        }
      }

      dateam
    } else {
      logger.warn("Missing team_players attribute in: %s".format(data.attributes))
    }
    dateam.toMap
}

2 个答案:

答案 0 :(得分:2)

使用Scala库来处理它。有一些基于杰克逊(Play的ScalaJson,例如 - 参见this article单独使用它),以及不基于杰克逊的图书馆(我的首选是Argonaut虽然你也可以使用Spray-Json)。

这些库和其他人解决了这个问题。手工操作很尴尬,容易出错,所以不要这样做。

答案 1 :(得分:1)

使用for理解(使用一些内置模式匹配)是合理的。我们还可以考虑Map是一个元组列表,在我们的(String, Object)类型的情况下。同样,我们将忽略此示例可能的异常,因此:

import scala.collection.mutable.HashMap

def convert(json: Map[String, Object]): HashMap[Int, Seq[String]] = {

  val converted = for {
    (id: String, description: Seq[Any]) <- json
  } yield (id.toInt, description.map(_.toString))

  HashMap[Int, Seq[String]](converted.toSeq: _*)
}

因此,我们的for理解只考虑(String, Seq[Any])类型的元组,然后将转换后的StringIntSeq[Any]合并为{{1} }。并使Seq[String]变得可变。