2012-10-25 9 views
5

Czy istnieje sposób na łatwe przeanalizowanie ciągu par klucz-wartość w klasie przypadku scala?Łatwo przeanalizuj łańcuch par Key = Value do klasy Scala: klasa

na przykład z następującym ciągiem

"consumer_key=1234ABC, consumer_secret=12345ABC" 

do

case class Auth(consumerKey:String, consumerSecret:String) 

lub nawet

case class Auth(consumer_key:String, consumer_secret:String) 
+0

Czy wszystkie struny mają taką strukturę? jeśli tak, dlaczego nie złamiesz tego wyraźnie? 'val (key, secret) = (s.slice (" consumer_key = ". length, s.indexOf (", ")), s.drop (s.lastIndexOf (" = ")))' –

+0

Nie właśnie wysłałem pierwsze dwa, ale jest ich więcej. –

Odpowiedz

9

Można użyć wyrażenia regularnego i dopasowywania wzoru:

scala> val R = "consumer_key=(.*), consumer_secret=(.*)".r 
R: scala.util.matching.Regex = consumer_key=(.*), consumer_secret=(.*) 

scala> "consumer_key=1234ABC, consumer_secret=12345ABC" match { 
    | case R(k, v) => Auth(k, v) 
    | } 
res0: Auth = Auth(1234ABC,12345ABC) 

Zastosowanie JavaTokenParsers dla bardziej elastycznego parsowania:

import scala.util.parsing.combinator._ 

case class Auth(consumerKey: String, consumerSecret: Option[String]) 

class AuthParser extends JavaTokenParsers { 
    def auth: Parser[Auth] = key ~ opt("," ~> secret) ^^ { case k ~ s => Auth(k, s)} 
    def key: Parser[String] = value("consumer_key") 
    def secret: Parser[String] = value("consumer_secret") 
    def value(k: String): Parser[String] = k ~ "=" ~> "[^,]*".r 
    def apply(s: String) = parseAll(auth, s) 
} 

Zastosowanie:

scala> val p = new AuthParser 
p: AuthParser = [email protected] 

scala> p("consumer_key=1234ABC, consumer_secret=12345ABC").get 
res0: Auth = Auth(1234ABC,Some(12345ABC)) 

scala> p("consumer_key=1234ABC").get 
res1: Auth = Auth(1234ABC,None) 
+0

Dzięki temu to, czego szukałem, czy jest tak, aby jeden z nich był opcjonalny? –

+0

@AnthonyMcCormick: odpowiedź zaktualizowana dla opcjonalnego parametru 'consumer_secret'. – senia

2

Kocham biblioteki parserami Scala, ale to jest trochę powolny. Jeśli struny wszystkie wyglądają tak, można tak łatwo zrobić:

case class Auth(consumerKey:String, consumerSecret:String) 
object Auth { 
    def fromString(string: String): Seq[Auth] = string.split(", ").toSeq map { pair => 
    val lst = pair.split("=") 
    Auth(lst(0), lst(1)) 
    } 
} 
0

zgadzam się z nnythm ale to rozwiązanie nie rozwiązuje problemu. To może działać lepiej:

case class Auth(consumerKey:String, consumerSecret:String) 
object Auth { 
    def fromString(s: String): Auth = { 
    val p = s.split(", ").toSeq.map { pair => { 
     val lst = pair.split("=") 
     (lst(0), lst(1)) 
    }}.toMap 
    Auth(p("consumer_key"), p("consumer_secret")) 
    } 
} 

Ma to tę dodatkową zaletę, że jest w stanie mieć ciąg z dowolnej liczby par wartości kluczowych i można łatwo zmienić, które wybrać, aby pracować.

Powiązane problemy