Parsing error when trying to parse comma-delimited key-value pairs with values containing list separated by commas - regex

I have this class:
import scala.util.parsing.combinator.JavaTokenParsers
class RequestMappingParser extends JavaTokenParsers {
def key: Parser[String] = "value" | "method" | "consumes" | "params"
def singleValue: Parser[String] = """[^),]*""".r
def multipleValues: Parser[String] = "{" ~ repsep(ident, ",") ~ "}" ^^ {
case "{" ~ lst ~ "}" => lst.mkString(", ")
}
def value: Parser[String] = multipleValues | singleValue
def keyValue: Parser[(String, String)] = (key ~ "=" ~ value).map {
case k ~ _ ~ v => k -> v
}
def commaDelimitedSeq: Parser[Map[String, String]] = repsep(keyValue, ",").map(_.toMap)
def requestMapping: Parser[MethodRequestMapping] = ("#RequestMapping(" ~ commaDelimitedSeq ~ ")").map {
case _ ~ map ~ _ =>
val consumes = if (map.contains("consumes")) Some(map("consumes")) else None
val value = if (map.contains("value")) Some(map("value")) else None
val method = if (map.contains("method")) Some(map("method")) else None
val params = if (map.contains("params")) Some(map("params")) else None
new MethodRequestMapping(value = value, method = method, consumes = consumes, params = params)
}
}
I have this test:
test("#RequestMapping – params") {
val parser = new RequestMappingParser()
val requestMappingStr = """#RequestMapping(
| value = "/ex/bars",
| params = { "id", "second" },
| method = GET)""".stripMargin
val parseResult = parser.parse(parser.requestMapping, requestMappingStr)
val result = parseResult.get
assert(result.value.get.equals("\"/ex/bars\""))
assert(result.method.get.equals("GET"))
assert(result.params.get.equals("{ \"id\", \"second\" }"))
}
But the test is failing with this parsing error:
[3.18] failure: ')' expected but ',' found
params = { "id", "second" },
^
I am using Scala 2.13. What do I have wrong here?

import scala.util.parsing.combinator.JavaTokenParsers
class RequestMappingParser extends JavaTokenParsers {
def key: Parser[String] = "value" | "method" | "consumes" | "params"
def singleValue: Parser[String] = """[^),]*""".r
def multipleValues: Parser[String] = "{" ~ repsep(stringLiteral, ",") ~ "}" ^^ {
case "{" ~ lst ~ "}" => "{ " + lst.mkString(", ") + " }"
}
def value: Parser[String] = multipleValues | singleValue
def keyValue: Parser[(String, String)] = (key ~ "=" ~ value).map {
case k ~ _ ~ v => k -> v
}
def commaDelimitedSeq: Parser[Map[String, String]] = repsep(keyValue, ",").map(_.toMap)
def requestMapping: Parser[MethodRequestMapping] = ("#RequestMapping(" ~ commaDelimitedSeq ~ ")").map {
case _ ~ map ~ _ =>
val consumes = if (map.contains("consumes")) Some(map("consumes")) else None
val value = if (map.contains("value")) Some(map("value")) else None
val method = if (map.contains("method")) Some(map("method")) else None
val params = if (map.contains("params")) Some(map("params")) else None
new MethodRequestMapping(value = value, method = method, consumes = consumes, params = params)
}
}

Related

How to get integer with regular expression in kotlin?

ViewModel
fun changeQty(textField: TextFieldValue) {
val temp1 = textField.text
Timber.d("textField: $temp1")
val temp2 = temp1.replace("[^\\d]".toRegex(), "")
Timber.d("temp2: $temp2")
_qty.value = textField.copy(temp2)
}
TextField
OutlinedTextField(
modifier = Modifier
.focusRequester(focusRequester = focusRequester)
.onFocusChanged {
if (it.isFocused) {
keyboardController?.show()
}
},
value = qty.copy(
text = qty.text.trim()
),
onValueChange = changeQty,
label = { Text(text = qtyHint) },
singleLine = true,
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Number,
imeAction = ImeAction.Done
),
keyboardActions = KeyboardActions(
onDone = {
save()
onDismiss()
}
)
)
Set KeyboardType.Number, it display 1,2,3,4,5,6,7,8,9 and , . - space.
I just want to get integer like -10 or 10 or 0.
But I type the , or . or -(not the front sign), it show as it is.
ex)
typing = -10---------
hope = -10
display = -10---------
I put regular expression in
val temp2 = temp1.replace("[^\\d]".toRegex(), "")
But, it doesn't seem to work.
How I can get only integer(also negative integer)?
Use this regex (?<=(\d|-))(\D+) to replace all non digit characters, except first -.
fun getIntegersFromString(input: String): String {
val pattern = Regex("(?<=(\\d|-))(\\D+)")
val formatted = pattern.replace(input, "")
return formatted
}
Check it here

Regex RDD using Apache Spark Scala

I have the following RDD:
x: Array[String] =
Array("Et: NT=grouptoClassify,hadoop-exec,sparkConnection,Ready
group: NT=app_1,hadoop-exec,sparkConnection,Ready
group: NT=app_exmpl_2,DB-exec,MDBConnection,NR
group: NT=apprexec,hadoop-exec,sparkConnection,Ready
group: NT=nt_prblm_app,hadoop-exec,sparkConnection,NR
I just want to get the first part of every part of this RDD as you can see in the next example:
Et: NT=grouptoClassify
group: NT=app_1
group: NT=app_exmpl_2
group: NT=apprexec
group: NT=nt_prblm_app
To do it I am trying it in this way.
//Here I get the RDD:
val x = spark.sparkContext.parallelize(List(value)).collect()
//Try to use regex on it, this regex is to get until the first comma
val regex1 = """(^(.+?),)"""
val rdd_1 = x.map(g => g.matches(regex1))
This is what I am trying but is not working for me because I just get an Array of Boolean. What am I doing wrong?
I am new with Apache Spark Scala. If you need something more just tell me it. Thanks in advance!
try this.
val x: Array[String] =
Array(
"Et: NT=grouptoClassify,hadoop-exec,sparkConnection,Ready",
"group: NT=app_1,hadoop-exec,sparkConnection,Ready",
"group: NT=app_exmpl_2,DB-exec,MDBConnection,NR",
"group: NT=apprexec,hadoop-exec,sparkConnection,Ready",
"group: NT=nt_prblm_app,hadoop-exec,sparkConnection,NR")
val rdd = sc.parallelize(x)
val result = rdd.map(lines => {
lines.split(",")(0)
})
result.collect().foreach(println)
output:
Et: NT=grouptoClassify
group: NT=app_1
group: NT=app_exmpl_2
group: NT=apprexec
group: NT=nt_prblm_app
Try with this regex :
^\s*([^,]+)(_\w+)?
Demo
To implement this regex in your example, you can try :
val arr = Seq("Et: NT=grouptoClassify,hadoop-exec,sparkConnection,Ready",
"group: NT=app_1,hadoop-exec,sparkConnection,Ready",
"group: NT=app_exmpl_2,DB-exec,MDBConnection,NR",
"group: NT=apprexec,hadoop-exec,sparkConnection,Ready",
"group: NT=nt_prblm_app,hadoop-exec,sparkConnection,NR")
val rd_var = spark.sparkContext.parallelize((arr).map((Row(_))))
val pattern = "^\s*([^,]+)(_\w+)?".r
rd_var.map {
case Row(str) => str match {
case pattern(gr1, _) => gr1
}
}.foreach(println(_))
With RDD:
val spark = SparkSession.builder().master("local[1]").getOrCreate()
val pattern = "([a-zA-Z0-9=:_ ]+),(.*)".r
val el = Seq("Et: NT=grouptoClassify,hadoop-exec,sparkConnection,Ready",
"group: NT=app_1,hadoop-exec,sparkConnection,Ready",
"group: NT=app_exmpl_2,DB-exec,MDBConnection,NR",
"group: NT=apprexec,hadoop-exec,sparkConnection,Ready",
"group: NT=nt_prblm_app,hadoop-exec,sparkConnection,NR")
def main(args: Array[String]): Unit = {
val rdd = spark.sparkContext.parallelize((el).map((Row(_))))
rdd.map {
case Row(str) => str match {
case pattern(gr1, _) => gr1
}
}.foreach(println(_))
}
It gives:
Et: NT=grouptoClassify
group: NT=app_1
group: NT=app_exmpl_2
group: NT=apprexec
group: NT=nt_prblm_app

How do I transform a List[String] to a List[Map[String,String]] given that the list of string represents the keys to the map in Scala?

I have a list of references:
val references: List[String]= List("S","R")
I also have variables which is:
val variables: Map[String,List[String]]=("S"->("a","b"),"R"->("west","east"))
references is a list of keys of the variables map.
I want to construct a function which takes:
def expandReplacements(references:List[String],variables:Map[String,List[String]]):List[Map(String,String)]
and this function should basically create return the following combinations
List(Map("S"->"a"),("R"->"west"),Map("S"->"a"),("R"->"east"),Map("S"->"b"),("R"->"west"),Map("S"->"b"),("R"->"east"))
I tried doing this:
val variables: Map[String,List[String]] = Map("S" -> List("a", "b"), "R" -> List("east", "central"))
val references: List[String] = List("S","R")
def expandReplacements(references: List[String]): List[Map[String, String]] =
references match {
case ref :: refs =>
val variableValues =
variables(ref)
val x = variableValues.flatMap { variableValue =>
val remaining = expandReplacements(refs)
remaining.map(rem => rem + (ref -> variableValue))
}
x
case Nil => List.empty
}
If you have more than 2 references, you can do:
def expandReplacements(references: List[String], variables :Map[String,List[String]]): List[Map[String, String]] = {
references match {
case Nil => List(Map.empty[String, String])
case x :: xs =>
variables.get(x).fold {
expandReplacements(xs, variables)
} { variableList =>
for {
variable <- variableList.map(x -> _)
otherReplacements <- expandReplacements(xs, variables)
} yield otherReplacements + variable
}
}
}
Code run at Scastie.
So I have Figured it Out
def expandSubstitutions(references: List[String]): List[Map[String, String]] =
references match {
case r :: Nil => variables(r).map(v => Map(r -> v))
case r :: rs => variables(r).flatMap(v => expandSubstitutions(rs).map(expanded => expanded + (r -> v)))
case Nil => Nil
}
This Returns:
List(Map(R -> west, S -> a), Map(R -> east, S -> a), Map(R -> west, S -> b), Map(R -> east, S -> b))
Your references representation is suboptimal but if you want to use it...
val variables: Map[String,List[String]] = [S -> List("a", "b"), R -> List("east", "central")]
val references: List[String] = List("S","R")
def expandReplacements(references: List[String]): List[Map[String, String]] =
references match {
case List(aKey, bKey) =>
val as = variables.get(aKey).toList.flatten
val bs = variables.get(bKey).toList.flatten
as.zip(bs).map { case (a, b) =>
Map(aKey -> a, bKey -> b)
}
case _ => Nil
}

Parsing case statements in scala

Parsing case statements in scala
CASE WHEN col1 <> 0 AND col2 <> 0 THEN 'COL1 & COL2 IS NOT ZERO' ELSE 'COL1 & COL2 IS ZERO'
challenge here is to give all the scenarios where case statement can come for e.g. it can come inside a function. Also case statements/functions etc. can come inside another case statements which has to be handled.
This problem can be solved with scala parser combinator
first define the classes needed to map experssions
sealed trait Exp {
def asStr: String
override def toString: String = asStr
}
case class OperationExp(a: Exp, op: String, b: Exp, c: Option[String]) extends Exp { override def asStr = s"$a $op $b ${c.getOrElse("")}" }
case class CaseConditions(conditionValue: List[(String, String)] , elseValue: String, asAlias: Option[Exp]) extends Exp {
override def asStr = "CASE " + conditionValue.map(c => s"WHEN ${c._1} THEN ${c._2}").mkString(" ") + s" ELSE ${elseValue} END ${asAlias.getOrElse("")}"
}
now the solution
case class OperationExp(a: Exp, op: String, b: Exp, c: Option[String]) extends Exp { override def asStr = s"$a $op $b ${c.getOrElse("")}" }
case class CaseConditions(conditionValue: List[(String, String)] , elseValue: String, asAlias: Option[Exp]) extends Exp {
override def asStr = "CASE " + conditionValue.map(c => s"WHEN ${c._1} THEN ${c._2}").mkString(" ") + s" ELSE ${elseValue} END ${asAlias.getOrElse("")}"
}
val identifiers: Parser[String] = "[a-zA-Z0-9_~\\|,'\\-\\+:.()]+".r
val operatorTokens: Parser[String] = "[<>=!]+".r | ("IS NOT" | "IN" | "IS")
val conditionJoiner: Parser[String] = ( "AND" | "OR" )
val excludeKeywords = List("CASE","WHEN", "THEN", "ELSE", "END")
val identifierWithoutCaseKw: Parser[Exp] = Parser(input =>
identifiers(input).filterWithError(
!excludeKeywords.contains(_),
reservedWord => s"$reservedWord encountered",
input
)
) ^^ StrExp
val anyStrExp: Parser[Exp] = "[^()]*".r ^^ StrExp
val funcIdentifier: Parser[Exp] = name ~ ("(" ~> (caseConditionExpresionParser | funcIdentifier | anyStrExp) <~ ")") ^^ {case func ~ param => FunCallExp(func, Seq(param))}
val identifierOrFunctions = funcIdentifier | identifierWithoutCaseKw
val conditionParser: Parser[String] =
identifierOrFunctions ~ operatorTokens ~ identifierOrFunctions ~ opt(conditionJoiner) ^^ {
case a ~ op ~ b ~ c => s"$a $op $b ${c.getOrElse("")}"
}
def caseConditionExpresionParser: Parser[CaseConditions] = "CASE" ~ rep1("WHEN" ~ rep(conditionParser) ~ "THEN" ~ rep(identifierWithoutCaseKw)) ~ "ELSE" ~ rep(identifierWithoutCaseKw) ~ "END" ~ opt("AS" ~> identifierWithoutCaseKw)^^ {
case "CASE" ~ conditionValuePair ~ "ELSE" ~ falseValue ~ "END" ~ asName =>
CaseConditions(
conditionValuePair.map(cv => (
cv._1._1._2.mkString(" "),
parsePipes(cv._2.mkString(" ")).isRight match {
case true => parsePipes(cv._2.mkString(" ")).right.get
case _ => cv._2.mkString(" ")
}
)),
parsePipes(falseValue.mkString("")).isRight match {
case true => parsePipes(falseValue.mkString(" ")).right.get
case _ => falseValue.mkString("")
}, asName)
}
//this parser can be used to get the results
val caseExpression = caseConditionExpresionParser | funcIdentifier
def parsePipes(input: String): Either[Seq[ParsingError], String] = {
parse(caseExpression, input) match {
case Success(parsed, _) => Right(parsed.asStr)
case Failure(msg, next) => Left(Seq(ParsingError(s"Failed to parse $pipedStr: $msg, next: ${next.source}.")))
case Error(msg, next) => Left(Seq(ParsingError(s"Error in $pipedStr parse: $msg, next: ${next.source}.")))
}
}

how we find and replace array dictionary value in swift 3

My array has this dictionary I want to find and replace where dictionary h
attendance = "" and attendance = "A" and replace with attendance = "P"
I am using this:
checkedArray = [[String : AnyObject]]()
let index = find(checkedArray) { $0["attendance"] == "P" }
if let index = index {
checkedArray[index] = newDictionary
}
// Do any additional setup after loading the view.
}
func find<C: CollectionType>(collection: C, predicate: (C.Generator.Element) -> Bool) -> C.Index? {
for index in collection.startIndex ..< collection.endIndex {
if predicate(collection[index]) {
return index
}
}
return nil
}
[
{"studentID":"12","name":"panky","roll":"","attendance":"P"},
{"studentID":"14","name":"a","roll":"","attendance":""},
{"studentID":"4","name":"akshay","roll":"1","attendance":"E"},
{"studentID":"6","name":"anki","roll":"11","attendance":"P"},
{"studentID":"1","name":"mohit","roll":"2","attendance":"M"},
{"studentID":"5","name":"yogi","roll":"22","attendance":"L"},
{"studentID":"3","name":"Neha","roll":"3","attendance":"A"}
]
let dic: [[String : Any]] = [
["studentID":"12","name":"panky","roll":"","attendance":"P"],
["studentID":"14","name":"a","roll":"","attendance":""],
["studentID":"4","name":"akshay","roll":"1","attendance":"E"],
["studentID":"6","name":"anki","roll":"11","attendance":"P"],
["studentID":"1","name":"mohit","roll":"2","attendance":"M"],
["studentID":"5","name":"yogi","roll":"22","attendance":"L"],
["studentID":"3","name":"Neha","roll":"3","attendance":"A"]
]
let result : [Any] = dic.map { dictionary in
var dict = dictionary
if let attendance = dict["attendance"] as? String, attendance == "" || attendance == "A" {
dict["attendance"] = "P"
}
return dict
}