将不同类型映射到String

时间:2017-10-08 07:28:07

标签: scala functional-programming

我正在尝试学习Scala中的一些函数式编程。

我有这张地图:

val params: Map[String, QueryMap] = Map(
  "a" -> SimpleQueryVal("1"),
  "b" -> ComplexQueryVal("2", "3")
)

QueryMap的位置(可能不是最好的方法):

sealed trait QueryMap
case class SimpleQueryVal(value: String) extends QueryMap
case class ComplexQueryVal(values: String*) extends QueryMap

我的结果是有一个类似查询参数的字符串:?a = 1& b = 2& b = 3

我尝试了一些东西,但是我的方法返回一个Iterator [String],即使我使用mkString,看起来很难看,我相信这是一种非常简单的方法。

def paramString(queryMap: Map[String, QueryMap]) = queryMap.keys.map { key =>
  val params = queryMap(key) match {
    case SimpleQueryVal(x) => "%s=%s".format(key, x)
    case complexQuery: ComplexQueryVal => complexQuery.values.map { value =>
      "%s=%s".format(key, value)
    }
  }
  val result: String = params match {
    case s: String => s + "&"
    case s: ArrayBuffer[_] => s.mkString("&")
  }
  result.mkString
}

我很感激任何可以让我今天学到东西的想法。 :)

3 个答案:

答案 0 :(得分:3)

I think the result String can be built in a simpler, more straight forward, manner.

def paramString(queryMap: Map[String, QueryMap]): String = queryMap.map{
  case (k, sq: SimpleQueryVal) => s"$k=${sq.value}"
  case (k, cq: ComplexQueryVal)=> cq.values.map(k + "=" + _).mkString("&")
}.mkString("&")

答案 1 :(得分:3)

A little cleaner:

def paramString(queryMap: Map[String, QueryMap]) = queryMap.flatMap {
  case (key, SimpleQueryVal(x)) => Seq(s"$key=$x")
  case (key, ComplexQueryVal(values @ _*)) => values.map {v =>
    s"$key=$v"
  }
}.mkString("&")

No need for ArrayBuffer or to repeat the .mkString("&").

Keep in mind that this is good for just learning. If you're actually trying to handle HTTP query string parameters, you need to URLEncode the keys and the values and there's probably better libraries for that.

答案 2 :(得分:1)

Try this:

def paramString(queryMap: Map[String, QueryMap]) = {
  val qParams = queryMap.keys.map { key =>
    queryMap(key) match {
      case SimpleQueryVal(x) => "%s=%s".format(key, x)
      case complexQuery: ComplexQueryVal => complexQuery.values.map { value =>
        "%s=%s".format(key, value)
      }.mkString("&")
    }
  }
  qParams.mkString("&")
}

println(paramString(params))

Here, first you get a Set[String] like a=1 or b=2&b=3. Then you simply do another .mkString("&") to concatenate them all.