2012-04-02 14 views
1

Ich habe String wie {param1=foo}{param2=bar}hello world!
Ich brauche Array von Tupeln zu extrahieren (paramName, value) aus dieser Zeichenfolge und bekommen so etwas wie [(param1, foo), (param2, bar)]Tupeln aus Zeichenfolge durch reguläre Ausdrücke in Scala

Ist es möglich, in Scala extrahiere diese Tupel durch nur eine Regex? Weil ich das nur in der Weise wie

val str = "{param1=foo}{param2=bar}hello world!" 
val param = """(?<=\{)(.+?)(?=\})""".r // extract everything between { and } 
val keyValue = """(.+)=(.+)""".r // for extracting key and value 
val parameters = for (keyValue(key,value) <- param.findAllIn(str).toArray) 
        yield (key,value) 

tun konnte, und es sieht nicht süß aus.

Auch habe ich versucht,

val param = """(?<=\{)(.+?)=(.+?)(?=\})""".r 

zu verwenden, aber es zurückgeben param=value als eine Zeichenfolge

Antwort

4

Hier ist ein Ausdruck, der Dinge wie {A=B} wo A und B finden enthalten {, } oder = nicht.

scala> val Re = """\{([^{}=]+)=([^{}=]+)\}""".r 

scala> val Re(a,b) = "{param1=foo}" 
a: String = param1 
b: String = foo 

Und wenn Sie alle Spiele in einem String finden wollen:

scala> val s = "{param1=foo}{param2=bar}hello world!" 

scala> Re.findAllIn(s).matchData.map(_.subgroups).toList 
res9: List[List[String]] = List(List(param1, foo), List(param2, bar)) 
+0

Ja! Das sind die Droiden, nach denen ich suche! – SquAreRoot

2

Ohne regex können Sie tun:

scala> val str = "{param1=foo}{param2=bar}hello world!" 

scala> str split '}' filter(x => x.head =='{' && x.contains('=')) map{x => val Array(key, value) = x.tail split '='; key -> value } 
res9: Array[(java.lang.String, java.lang.String)] = Array((param1,foo), (param2,bar)) 

Oder übersichtlicher:

// We find different blocks 
val str1 = str split '}' 

// We remove invalid blocks (end of the String in your case) 
val str2 = str1 filter(x => x.head == '{' && x.contains('=')) 

// We transform the String into a tupple, removing the head 
val str3 = str2 map{x => 
    val Array(key, value) = x.tail split '=' 
    key -> value 
} 
+2

Sehr schön :) aber imperativ-wie Element nach Index zu nehmen, können Sie tun, Muster-Matching 'val Array (Schlüssel, Wert) = x.tail split "="; Schlüssel -> Wert. – 4e6

+0

In der Tat, das ist besser, ich kannte den 'Schlüssel -> Wert'-Äquivalent nicht. –

+1

Bitte verwenden Sie keine Klammern und geschweifte Klammern in einem Ausdruck. Das sieht hässlich aus. 'str2 map {x => ...}' ist völlig ausreichend. – sschaef