2017-10-08 74 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鍵和值,可能有更好的庫。