2016-07-14 11 views
1

Gegeben ist eine Skalareichweite, die eine Auflistung von Schlüssel/Wert-Paaren aufweist (in der Reihenfolge Schlüsseltyp-Paar nicht festgelegt, Anzahl der Schlüssel/Wert-Paare nicht festgelegt):Schnelle Möglichkeit zum Extrahieren von Token aus einer Skalareiche

val s = "key1: val1, key2: (val2.1, val2.2, val2.3), key3:(), key4: val4" 

ich brauche diese in einer unveränderlichen Karte ziehen wie:

Map("key1" -> "val1", 
    "key2" -> "(val2.1, val2.2, val2.3)", 
    "key3" -> "()", 
    "key4" -> "val4") 

habe ich versucht, dies:

val kvMap = s.split(", ").map(_.split(": ")).map(t => t(0) -> t(1)).toMap 

Dies ist jedoch fehlgeschlagen, da in Klammern und zwischen den Schlüssel/Wert-Paaren dasselbe Trennzeichen (Komma) verwendet wird.

Ich könnte es mit einem Stapel mit Iteration tun, aber das vermeiden wollen.

Ich habe auch versucht, einen regulären Ausdruck zu schreiben, die mir dabei helfen könnte, aber es könnte nur für 1 Paar Arbeits erhalten:

scala> val MyPattern = "([^=]*):(.*)".r 
Pattern: scala.util.matching.Regex = ([^=]*):(.*) 
         ^
scala> val MyPattern(k, v) = "key: value" 
k: String = key 
v: String = " value" 

Ich suche eine funktionale Möglichkeit, diese Operation zu tun.

Antwort

5

Wenn Ihre Schlüssel-Wert-Paare nicht verschachtelt Klammern haben, können Sie einen regulären Ausdruck verwenden, mit Komma + Raum zu teilen, die mit beliebigen Zeichen nicht befolgt werden außer ( und ) bis zu einem ):

""", (?![^()]*\))""".r 

siehe die regex demo

Erklärung:

  • , - passen Sie ein Komma und ein Leerzeichen, nachdem es nur, wenn ...
  • (?![^()]*\)) - nicht mit nicht ) und nicht ) (0 oder mehrmals), gefolgt folgte mit einer wörtlichen ) (das heißt, wenn nicht gefolgt mit etwas + )).

Wenn Sie mit einem passenden Ansatz versuchen:

"""([^=:]*):\s*(.*?),?\s*(?=$|\w+:)""".r 

Siehe this demo

Einzelheiten:

  • ([^=:]*) - Gruppe 1 Capturing 0+ andere Zeichen als = und : (vielleicht eine * sollte mit + ersetzt werden, da die Schlüssel nicht leer sein kann)
  • :\s* - ein Doppelpunkt mit 0+ Whitespaces
  • (.*?),?\s* - beliebige Zeichen aber eine neue Zeile so wenig wie möglich (Gruppe 2, (.*?)), die mit einem optionalen gefolgt werden , und 0+ Leerzeichen
  • (?=$|\w+:) - die entweder mit dem Ende der Zeichenfolge oder 1 + Wort Zeichen und einem Doppelpunkt gefolgt werden.
+1

Perfekt! Das ist fantastisch! –

Verwandte Themen