2012-10-25 4 views
5

Gibt es eine Möglichkeit, eine Zeichenfolge von Schlüsselwertpaare in einer Scala-Fallklasse einfach zu analysieren?Pars leicht String von Schlüssel = Wert-Paaren zu Scala-Fall-Klasse

zum Beispiel aus der folgenden Zeichenkette

"consumer_key=1234ABC, consumer_secret=12345ABC" 

in

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

oder sogar

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

haben alle Ihre Saiten diese Struktur? Wenn ja, warum brechen Sie es nicht explizit? 'val (key, secret) = (s.slice (" consumer_key = ". length, s.indexOf (", ")), s.drop (s.lastIndexOf (" = ")))' –

+0

Nein, ich habe gerade gepostet die ersten beiden aber es gibt mehr. –

Antwort

9

Sie können regex und Pattern-Matching verwenden:

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) 

Verwenden flexiblere Analyse:

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

Verbrauch:

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

Danke das ist, was ich gesucht habe, gibt es überhaupt einen von ihnen optional zu machen? –

+0

@AnthonyMcCormick: Antwort wurde für das optionale 'consumer_secret' aktualisiert. – senia

2

Ich liebe die scala Parser Bibliothek, aber es ist ein wenig langsam. Wenn die Saiten alle so aussehen, können Sie genauso gut tun:

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

Ich stimme mit nnythm aber diese Lösung nicht das Problem lösen. Dies kann besser arbeiten:

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

Dies hat den zusätzlichen Vorteil, eine Zeichenfolge mit einer beliebigen Anzahl von Schlüssel-Wert-Paare aufweisen kann und Sie können leicht ändern, die Sie wählen, um mit zu arbeiten.