2017-10-08 102 views
1

我想在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,看起来很丑,我相信有一个ve简单的做法。

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

我认为结果String可以建立在一个更简单,更直接的方式。

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

试试这个:

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)) 

这里,首先你会得到一个Set[String]a=1b=2&b=3。然后你只需再做一个.mkString("&")来连接它们。

3

干净了一点:

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("&") 

无需ArrayBuffer或重复.mkString("&")

请记住,这对于刚刚学习很有用。如果你真的想要处理HTTP查询字符串参数,你需要URLEncode键和值,可能有更好的库。