How to read Map values from foreach in scala - json

// Reads Json file
val input_file = ("\\path\\to\\MyNew.json");
val json_content = scala.io.Source.fromFile(input_file).mkString
// parsing the json file
val details = JSON.parseFull(json_content)
// checking the matched result
details match {
case mayBeList: Some[Map[String, Any]] =>
val z = mayBeList.get.tails.toSet.flatten
z.foreach(println)
case None => println("Parsing failed")
case other => println("Unknown data structure: " + other)
}
getting following Output:
Map(Name -> Harish, Company -> In Equity, Sal -> 50000)
Map(Name -> Veer, Company -> InOut, Sal -> 20000)
Map(Name -> Zara, Company -> InWhich, Sal -> 90000)
Map(Name -> Singh, Company -> InWay, Sal -> 30000)
Map(Name -> Chandra, Company -> InSome, Sal -> 60000)
Expected Output
Harish, In Quality, 50000- (only values of Map)

Use .values for the values and .keys for the keys.
val m: Map[String, Int] = Map("a" -> 1, "b" -> 2)
m.values // res0: Iterable[Int] = MapLike(1, 2)
m.keys // res1: Iterable[String] = Set(a, b)

All you need is to iterate though the elements of your list i.e. z and extract values from each map like this,
List(Map("Name" -> "Harish", "Company" -> "In Equity", "Sal" -> 50000),
Map("Name" -> "Veer", "Company" -> "InOut", "Sal" -> 20000),
Map("Name" -> "Zara", "Company" -> "InWhich", "Sal" -> 90000),
Map("Name" -> "Singh", "Company" -> "InWay", "Sal" -> 30000),
Map("Name" -> "Chandra", "Company" -> "InSome", "Sal" -> 60000)
)
.map(_.values.toList).foreach(println)
//List[List[Any]] = List(List(Harish, In Equity, 50000), List(Veer, InOut, 20000), List(Zara, InWhich, 90000), List(Singh, InWay, 30000), List(Chandra, InSome, 60000))
Hope this helps you.
Update
In response to your comment, use this code
import scala.util.parsing.json._
val input_file = ("C:\\Users\\VishalK\\IdeaProjects\\ScalaCassan\\src\\main\\scala\\MyNew.json");
val json_content = scala.io.Source.fromFile(input_file)
// parsing the json file
val details: Option[Any] = JSON.parseFull(json_content.mkString)
details match {
case mayBeList: Some[Any] =>
mayBeList.getOrElse(Seq.empty[Map[String, Any]]).asInstanceOf[List[Map[String, Any]]].map(_.values.toList).toSet
case None => println("Parsing failed")
}
in your match block :
In first case I don't get why you are using .tails.toSet.flatten on Any data type.
You can remove the third case as Some and None are the only possible outcomes of Option data-type.

scala> val l = List(Map("Name" -> "Harish", "Company" -> "In Equity", "Sal" -> 50000),
| Map("Name" -> "Veer", "Company" -> "InOut", "Sal" -> 20000),
| Map("Name" -> "Zara", "Company" -> "InWhich", "Sal" -> 90000),
| Map("Name" -> "Singh", "Company" -> "InWay", "Sal" -> 30000),
| Map("Name" -> "Chandra", "Company" -> "InSome", "Sal" -> 60000)
| )
l: List[scala.collection.immutable.Map[String,Any]] = List(Map(Name -> Harish, Company -> In Equity, Sal -> 50000), Map(Name -> Veer, Company -> InOut, Sal -> 20000), Map(Name -> Zara, Company -> InWhich, Sal -> 90000), Map(Name -> Singh, Company -> InWay, Sal -> 30000), Map(Name -> Chandra, Company -> InSome, Sal -> 60000))
scala> l.map(_.values).foreach(x => println(x.toList.mkString(", ")))
Harish, In Equity, 50000
Veer, InOut, 20000
Zara, InWhich, 90000
Singh, InWay, 30000
Chandra, InSome, 60000

Related

How to decode a JSON array into Elm list of custom types

I want to decode a JSON array of payload objects into List Payload where each Payload is a custom type:
type Payload
= PayloadP1 P1
| PayloadP2 P2
After decoding PayloadP1 and PayloadP2 using decoders below how do I decode Payload?
type alias P1 =
{ id : Int
, st : String
}
type alias P2 =
{ id : Int
, s1 : String
, s2 : String
}
type Payload
= PayloadP1 P1
| PayloadP2 P2
type alias PayloadQueue = List Payload
decodeP1 : Jd.Decoder P1
decodeP1 =
Jd.map2 P1
(Jd.field "id" Jd.int)
(Jd.field "st" Jd.string)
decodeP2 : Jd.Decoder P2
decodeP2 =
Jd.map3 P2
(Jd.field "id" Jd.int)
(Jd.field "p1" Jd.string)
(Jd.field "p2" Jd.string)
decodePayload =
Jd.field ".type" Jd.string
|> Jd.andThen decodePayload_
{-
decodePayload_ : String -> Jd.Decoder Payload
decodePayload_ ptype =
case ptype of
"P1" -> decodeP1
"P2" -> decodeP2
-}
json_str = """[
{".type" : "P1", "id" : 1, "st" : "st"},
{".type" : "P2", "id" : 2, "p1" : "p1", "p2" : "p2"},
]"""
You need to wrap P1 and P2 in PayloadP1 and PayloadP2 respectively in order to return a common type from each branch, which you can do using map. Then you also need to account for the possibility that the type field is neither P1 or P2. In that case you can either provide a default or return an error using fail. I've done the latter below.
decodePayload_ : String -> Jd.Decoder Payload
decodePayload_ ptype =
case ptype of
"P1" -> decodeP1 |> Jd.map PayloadP1
"P2" -> decodeP2 |> Jd.map PayloadP2
_ -> Jd.fail "invalid type"

Prove transformation between data types correctness

I have two data types and a transformation function to convert from one to another
data TTerm : Set where
TVar : Nat -> TTerm
TPrim : TPrim' -> TTerm
TDef : QName -> TTerm
TCon : QName -> TTerm
TLam : TTerm -> TTerm
TApp : TTerm -> List TTerm -> TTerm
TLet : TTerm -> TTerm -> TTerm
TLit : Literal -> TTerm
TErased : TTerm
TError : TError' -> TTerm
data GoTerm : Set where
Self : GoTerm
Local : LocalId -> GoTerm
Global : GlobalId -> GoTerm
GoVar : Nat -> GoTerm
GoSwitch : GoTerm -> List GoTerm -> GoTerm
GoCase : MemberId -> Nat -> Nat -> Nat -> List GoTerm -> GoTerm
GoMethodCall : MemberId -> List GoTerm -> GoTerm
GoMethodCallParam : GoTerm -> TypeId -> GoTerm
GoCreateStruct : MemberId -> List GoTerm -> GoTerm
GoIf : GoTerm -> GoTerm -> GoTerm -> GoTerm
GoLet : String -> GoTerm -> GoTerm -> GoTerm
PrimOp : GoTerm -> GoTerm -> GoTerm -> GoTerm
ReturnExpression : GoTerm -> TypeId -> GoTerm
GoInt : Nat -> GoTerm
Const : String -> GoTerm
UndefinedTerm : GoTerm
GoErased : GoTerm
Null : GoTerm
I have also created additional function that maps back from GoTerm to TTerm, so now I have two functions that do opposite things and would like to prove that a ≡ (decompileTerm (compileTerm a)). But so far have not found a way to do that, maybe someone could put me on the right tracks here?

Parsing nested collection in scala

I have a collection structure as shown below. I need to build the statement based on k,v pairs in the map. The level of nesting is not known prior and code needs to parse it dynamically.
Structure:
case class Step(id: Option[String], stepId: Option[String], parameters: Option[Map[String, Any]])
val sample = Step(id = Some("a1"), Some("case"), Some(
Map(
"CONDITIONAL" -> List(
Map("comparison" -> List(
Map("comparision" -> List(
Map("comparision" -> List(
Map("comparator" -> List(
Map(
"EVAL" -> "c11",
"OPERATION" -> "equals to",
"WHEN" -> List("A")),
Map(
"eval" -> "c12",
"operation" -> "in",
"when" -> List("B")),
Map(
"eval" -> "c13",
"operation" -> "starts with",
"when" -> List("C")
)),
"operator" -> "OR"
),
Map("comparator" -> List(
Map(
"EVAL" -> "c21",
"OPERATION" -> "equals to",
"WHEN" -> List("A")),
Map(
"eval" -> "c22",
"operation" -> "in",
"when" -> List("B")
)),
"operator" -> "OR"
)),
"operator" -> "AND"
),
Map("comparator" -> List(
Map(
"EVAL" -> "c31",
"OPERATION" -> "equals to",
"WHEN" -> List("A")),
Map(
"EVAL" -> "c32",
"OPERATION" -> "in",
"WHEN" -> List("B")),
Map(
"EVAL" -> "c33",
"OPERATION" -> "starts with",
"WHEN" -> List("C")
)),
"operator" -> "OR"
)),
"operator" -> "OR"
)),
"THEN" -> "result"
)),
"ELSE" -> "default"
))
)
val stepsLower = sample.parameters.get.map(p => p._1.toLowerCase -> p._2)
val comparisons = stepsLower("conditional").asInstanceOf[List[Map[String, Any]]]
Now I need to parse data under the conditional (in comparisons) by evaluating the structure.
The result should be ((c11 OR c12 OR c13 ) AND (c21 OR c22)) OR (c31 OR c32 OR c33 OR c34)
Here is the code snippet that should work for all your use cases.
case class Step(id: Option[String], stepId: Option[String], parameters: Option[Map[String, Any]])
val sample1 = Step(id = Some("a1"), Some("case"), Some(Map(
"CONDITIONAL" -> List(
Map("comparison" -> List(
Map("comparison" -> List(
Map("comparison" -> List(
Map("comparator" -> List(
Map(
"eval" -> "c11",
"operation" -> "equals to",
"when" -> List("A")),
Map(
"eval" -> "c12",
"operation" -> "in",
"when" -> List("B")),
Map(
"eval" -> "c13",
"operation" -> "starts with",
"when" -> List("C")
)),
"operator" -> "OR"
),
Map("comparator" -> List(
Map(
"eval" -> "c21",
"operation" -> "equals to",
"when" -> List("A")),
Map(
"eval" -> "c22",
"operation" -> "in",
"when" -> List("B")
)),
"operator" -> "OR"
)),
"operator" -> "AND"
),
Map("comparator" -> List(
Map(
"eval" -> "c31",
"operation" -> "equals to",
"when" -> List("A")),
Map(
"eval" -> "c32",
"operation" -> "in",
"when" -> List("B")),
Map(
"eval" -> "c33",
"operation" -> "starts with",
"when" -> List("C")
)),
"operator" -> "OR"
)),
"operator" -> "OR"
)),
"then" -> "result"
)),
"else" -> "default"
))
)
val sample2 = Step(id = Some("a1"), Some("case"), Some(
Map(
"conditional" -> List(
Map("comparison" -> List(
Map("comparison" -> List(
Map("comparator" -> List(
Map(
"eval" -> "c11",
"operation" -> "equals to",
"when" -> List("A")),
Map(
"eval" -> "c12",
"operation" -> "in",
"when" -> List("B", "b"))),
"operator" -> "AND"),
Map("comparator" -> List(
Map("eval" -> "c21",
"operation" -> "equals to",
"when" -> List("A")),
Map("eval" -> "c31",
"operation" -> "equals to",
"when" -> List("A"))),
"operator" -> "OR")),
"operator" -> "OR")),
"then" -> "something"
),
Map("comparison" -> List(
Map("comparison" -> List(
Map("comparator" -> List(
Map(
"eval" -> "c111",
"operation" -> "equals to",
"when" -> List("A")),
Map(
"eval" -> "c121",
"operation" -> "in",
"when" -> List("B", "b"))
),
"operator" -> "AND"),
Map("comparator" -> List(
Map(
"eval" -> "c212",
"operation" -> "equals to",
"when" -> List("A")),
Map(
"eval" -> "c313",
"operation" -> "equals to",
"when" -> List("A"))
),
"operator" -> "OR")),
"operator" -> "AND")),
"then" -> "somethingelse")
),
"else" -> "default"
)
))
def constructCase(c: List[Map[String, Any]], parentOp: Option[String] = None, parentThen: Option[String] = None): String = {
val result = c.map { x =>
val currentOp: Option[String] = x.get("operator").asInstanceOf[Option[String]]
val currentThen: Option[String] = x.get("then").asInstanceOf[Option[String]]
if (x contains "comparator") {
"(" + x("comparator").asInstanceOf[List[Map[String, Any]]].map(x => s"${x("eval")} ${x("operation")} ${x("when").asInstanceOf[List[String]].mkString(",")}").mkString(" " + currentOp.getOrElse("") + " ") + ")"
} else {
val tmp = constructCase(x("comparison").asInstanceOf[List[Map[String, Any]]], currentOp, currentThen)
if (tmp contains "WHEN") tmp else "(" + tmp + ")"
}
}.mkString(if (parentOp.isDefined) s" ${parentOp.get} " else "")
if (parentThen.isDefined) s"WHEN $result THEN ${parentThen.get}\n" else result.trim
}
val samples = Set(sample1, sample2)
samples.foreach { sample =>
val stepsLower = sample.parameters.get.map(p => p._1.toLowerCase -> p._2)
val comparisons = stepsLower("conditional").asInstanceOf[List[Map[String, Any]]]
println("CASE \n" + constructCase(comparisons) + s"\nELSE ${stepsLower("else")}")
println("")
}
Here is the result
CASE
WHEN (((c11 equals to A OR c12 in B OR c13 starts with C) AND (c21 equals to A OR c22 in B)) OR (c31 equals to A OR c32 in B OR c33 starts with C)) THEN result
ELSE default
CASE
WHEN ((c11 equals to A AND c12 in B,b) OR (c21 equals to A OR c31 equals to A)) THEN something
WHEN ((c111 equals to A AND c121 in B,b) AND (c212 equals to A OR c313 equals to A)) THEN somethingelse
ELSE default
Let me know if it doesn't work for any of your use case.

How to convert a Map to a Json in play scala

How can I convert the following Map structure which is a Map[String,Any] to a Json in scala? I am using Play.
val result = s
.groupBy(_.dashboardId)
.map(
each => Map(
"dashboardId" -> each._1,
"cubeId" -> each._2.head.cubeid,
"dashboardName" -> each._2.head.dashboardName,
"reports" -> each._2.groupBy(_.reportId).map(
reportEach => Map(
"reportId" -> reportEach._1,
"reportName" -> reportEach._2.head.reportName,
"selectedColumns" -> reportEach._2.groupBy(_.selectedColumnid).map(
selectedColumnsEach => Map(
"selectedColumnId" -> selectedColumnsEach._1,
"columnName" ->
selectedColumnsEach._2.head.selectColumnName.orNull,
"seq" ->selectedColumnsEach._2.head.selectedColumnSeq,
"formatting" -> selectedColumnsEach._2
)
)
)
)
)
)
You cannot convert a Map[String, Any] to Json but you can convert a Map[String, String] or Map[String, JsValue].
In your case, you can do by converting each map value to a JsValue before hand with:
Map(
"dashboardId" -> Json.toJson(each._1),
"cubeId" -> Json.toJson(each._2.head.cubeid),
"dashboardName" -> Json.toJson(each._2.head.dashboardName),
"reports" -> Json.toJson(each._2.groupBy(_.reportId).map(
reportEach => Map(
"reportId" -> Json.toJson(reportEach._1),
"reportName" -> (reportEach._2.find(_.reportName != null) match {
case Some(reportNameData) => Json.toJson(reportNameData.reportName)
case None => JsNull
})),
...
)
I read the results into a Seq[Map[String,Any]] by using .toSeq and then used toJson to convert it into a Json this worked.
val s = new SaveTemplate getReportsWithDashboardId(dashboardId)
val result : Seq[Map[String,Any]] = s.groupBy(_.dashboardId)
.map(
each => Map(
"dashboardId" -> each._1,
"cubeId" -> each._2.head.cubeid,
"dashboardName" -> each._2.head.dashboardName,
"reports" -> each._2.groupBy(_.reportId).map(
reportEach => Map(
"reportId" -> reportEach._1,
"reportName" -> (reportEach._2.find(_.reportName != null) match {
case Some(reportNameData) => reportNameData.reportName
case None => null
}),
"selectedColumns" -> reportEach._2.groupBy(_.selectedColumnid).map(
selectedColumnsEach => Map(
"selectedColumnId" -> selectedColumnsEach._1,
"columnName" -> selectedColumnsEach._2.head.selectColumnName.orNull,
"seq" ->selectedColumnsEach._2.head.selectedColumnSeq,
"formatting" -> Map(
"formatId" -> (selectedColumnsEach._2.find(_.formatId != null) match {
case Some(reportNameData) => reportNameData.formatId
case None => null
}),
"formattingId" -> (selectedColumnsEach._2.find(_.formattingid != null)
match {
case Some(reportNameData) => reportNameData.formattingid
case None => null
}),
"type" -> (selectedColumnsEach._2.find(_.formattingType != null) match
{
case Some(reportNameData) => reportNameData.formattingType
case None => null
})
)
)
)
)
)
)
).toSeq
val k = toJson(result)
Ok(k)

What is the Scala way of summing fields of list of tuples?

I want to reduce list of tuples that have a common field such as x by summing y fields.
Input:
List(("x" -> "foo", "y" -> 1000),
("x" -> "foo", "y" -> 1),
("x" -> "bar", "y" -> 101))
Output:
List(("x" -> "foo", "y" -> 1001),
("x" -> "bar", "y" -> 101))
What is the good approach for that? foldLeft or reduce?
Your item should be tuple:
List(("x" -> "foo", "y" -> 1000),("x" -> "foo", "y" -> 1), ("x" -> "bar", "y" -> 101))
use groupBy to group your key, and mapValues to generate the target:
List(("x" -> "foo", "y" -> 1000),("x" -> "foo", "y" -> 1), ("x" -> "bar", "y" -> 101))
.groupBy(x => x._1)
.mapValues(t => t.head._2._1 -> t.foldLeft(0.0)(_ + _._2._2))
The Output:
scala.collection.immutable.Map[(String, String),(String, Double)] =
Map((x,foo) -> (y,1001.0), (x,bar) -> (y,101.0))