Illegal start of declaration - scala

I have the following Scala code:
object Solution {
def main(args: Array[String]) {
val List(n, m) = readLine().split(" ").map(_.toInt).toList;
val knowledge: List[Set[Int]] = (0 until n).map( _ => {
val knows: List[Char] = readLine().toList;
(0 until m).toSet.flatMap(topic: Int => {
knows(topic) match {
case '1' => Set(topic);
case _ => Set[Int].empty;
}
});
}).toList;
val teams: List[Int] = knowledge.grouped(2).map{ case(x, y) => x ++ y }.map(_.size);
val best: Int = teams.max;
val count = teams.filter(_ == max);
println(best + " " + count);
}
}
On it, I am getting this error:
Solution.scala:16: error: illegal start of declaration
knows(topic) match {Solution.scala:
On this line:
knows(topic) match {
I can not understand what is wrong.
I am using a match in a body of a flatMap.
Any idea what is wrong with this code?

with the explicit type, you'll need
(topic: Int) =>
as per the syntax for an anonymous function
https://www.scala-lang.org/old/node/133
According to this answer, you can also move the type to
(0 until m).toSet[Int].flatMap(topic => {

Related

concateneate lines having same title

I have the following issue
Given this list in input , I want to concateneate integers for each line having the same title,
val listIn= List("TitleB,Int,11,0",
"TitleB,Int,1,0",
"TitleB,Int,1,0",
"TitleB,Int,3,0",
"TitleA,STR,3,0",
"TitleC,STR,4,5")
I wrote the following function
def sumB(list: List[String]): List[String] = {
val itemPattern = raw"(.*)(\d+),(\d+)\s*".r
list.foldLeft(ListMap.empty[String, (Int,Int)].withDefaultValue((0,0))) {
case (line, stri) =>
val itemPattern(k,i,j) = stri
val (a, b) = line(k)
line.updated(k, (i.toInt + a, j.toInt + b))
}.toList.map { case (k, (i, j)) => s"$k$i,$j" }
}
Expected output would be:
List("TitleB,Int,16,0",
"TitleA,STR,3,0",
"TitleC,STR,4,5")
Since you are looking to preserve the order of the titles as they appear in the input data, I would suggest you to use LinkedHashMap with foldLeft as below
val finalResult = listIn.foldLeft(new mutable.LinkedHashMap[String, (String, String, Int, Int)]){ (x, y) => {
val splitted = y.split(",")
if(x.keySet.contains(Try(splitted(0)).getOrElse(""))){
val oldTuple = x(Try(splitted(0)).getOrElse(""))
x.update(Try(splitted(0)).getOrElse(""), (Try(splitted(0)).getOrElse(""), Try(splitted(1)).getOrElse(""), oldTuple._3+Try(splitted(2).toInt).getOrElse(0), oldTuple._4+Try(splitted(3).toInt).getOrElse(0)))
x
}
else {
x.put(Try(splitted(0)).getOrElse(""), (Try(splitted(0)).getOrElse(""), Try(splitted(1)).getOrElse(""), Try(splitted(2).toInt).getOrElse(0), Try(splitted(3).toInt).getOrElse(0)))
x
}
}}.mapValues(iter => iter._1+","+iter._2+","+iter._3+","+iter._4).values.toList
finalResult should be your desired output
List("TitleB,Int,16,0", "TitleA,STR,3,0", "TitleC,STR,4,5")

folding in scala clarification

Want to improve piece of code by folding operation
this code works
var r = 0
arr.foreach { s =>
val count = arr.count(_ == s)
if (count > r) r = count
}
But in case with fold. I have an error with types.
Error:(44, 49) type mismatch;
found : (Int, String) => Any
required: (Any, Any) => Any
arr.fold(0: Int)((result: Int, s: String) => {
^
arr.fold(0: Int)((result: Int, s: String) => {
val count = arr.count(_ == s)
if (count > result) count
})
What is wrong ?
If you're trying to find the string with most occurrences in the the array, you can use groupBy:
val arr = Array("yuval", "yuval", "david")
arr.groupBy(identity).mapValues(_.length).max._2
arr: Array[String] = Array(yuval, yuval, david)
res1: Int = 2
If you really want to jump to hoops of using fold, you'll either need foldLeft or foldRight which pass the accumulator along for each value in the sequence:
val arr = Array("yuval", "yuval", "david")
val aggregatedMap = arr.foldLeft(Map.empty[String, Int].withDefaultValue(0)) {
case (map, value) => map.updated(value, map(value) + 1)
}
println(aggregatedMap.max._2)

Type mismatch when using iterators

I'm getting this error when i run the below code -
type mismatch, found : scala.collection.immutable.IndexedSeq[Int] required: Range
Where I'm going wrong ?
Functions -
def calcRange(i: Int, r: List[Range]):List[Range] = r match {
case List() => List(new Range(i,i+1,1))
case r1::rs =>
if (r1.start-1==i) {new Range(i,r1.end,1):: rs; }
else if(r1.end==i){new Range(r1.start,r1.end+1,1)::rs}
else {r1::calcRange(i,rs)}
}
def recurseForRanges(l: Iterator[Int]):List[Range] = {
var ans=List[Range]()
while(l.hasNext){
val cur=l.next;
ans=calcRange(cur,ans)
}
ans
}
def rangify(l: Iterator[Int]):Iterator[Range] = recurseForRanges(l).toIterator
Driver code
def main(args: Array[String]) {
val x=rangify( List(1,2,3,6,7,8).toIterator ).reduce( (x,y) => x ++ y)
/** This line gives the error -type mismatch,
found : scala.collection.immutable.IndexedSeq[Int] required: Range */
}
You can check docs:
++[B](that: GenTraversableOnce[B]): IndexedSeq[B]
++ returns IndexedSeq, not another Range, Range cannot have "holes" in them.
One way to fix it is to change Ranges to IndexedSeqs before reducing. This upcasts the Range so that reduce could take function
(IndexedSeq[Int], IndexedSeq[Int]) => IndexedSeq[Int]
because now it takes
(Range, Range) => Range
But ++ actually returns IndexedSeq[Int] instead of Range hence the type error.
val x = rangify(List(1, 2, 3, 6, 7, 8).iterator).map(_.toIndexedSeq).reduce(_ ++ _)
You can as well do this kind of cast by annotating type:
val it: Iterator[IndexedSeq[Int]] = rangify(List(1,2,3,6,7,8).iterator)
val x = it.reduce(_ ++ _)
Note that your code can be simplified, without vars
def calcRange(r: List[Range], i: Int): List[Range] = r match {
case Nil =>
Range(i, i + 1) :: Nil
case r1 :: rs =>
if (r1.start - 1 == i)
Range(i, r1.end) :: rs
else if (r1.end == i)
Range(r1.start, r1.end + 1) :: rs
else
r1 :: calcRange(rs, i)
}
def recurseForRanges(l: Iterator[Int]): List[Range] = {
l.foldLeft(List.empty[Range])(calcRange)
}
def rangify(l: Iterator[Int]): Iterator[Range] = recurseForRanges(l).iterator
val x = rangify(List(1,2,3,6,7,8).iterator).map(_.toIndexedSeq).reduce(_ ++ _)
To explain what I've done with it:
Range has a factory method, you don't need new keyword, you don't need to specify by value because 1 is default.
You need no semicolons as well.
What you are doing in recurseForRanges is basically what foldLeft does, I just swapped arguments in calcRange it could be passed directly to foldLeft.

Value assignment inside for-loop in Scala

Is there any difference between this code:
for(term <- term_array) {
val list = hashmap.get(term)
...
}
and:
for(term <- term_array; val list = hashmap.get(term)) {
...
}
Inside the loop I'm changing the hashmap with something like this
hashmap.put(term, string :: list)
While checking for the head of list it seems to be outdated somehow when using the second code snippet.
The difference between the two is, that the first one is a definition which is created by pattern matching and the second one is a value inside a function literal. See Programming in Scala, Section 23.1 For Expressions:
for {
p <- persons // a generator
n = p.name // a definition
if (n startsWith "To") // a filter
} yield n
You see the real difference when you compile sources with scalac -Xprint:typer <filename>.scala:
object X {
val x1 = for (i <- (1 to 5); x = i*2) yield x
val x2 = for (i <- (1 to 5)) yield { val x = i*2; x }
}
After code transforming by the compiler you will get something like this:
private[this] val x1: scala.collection.immutable.IndexedSeq[Int] =
scala.this.Predef.intWrapper(1).to(5).map[(Int, Int), scala.collection.immutable.IndexedSeq[(Int, Int)]](((i: Int) => {
val x: Int = i.*(2);
scala.Tuple2.apply[Int, Int](i, x)
}))(immutable.this.IndexedSeq.canBuildFrom[(Int, Int)]).map[Int, scala.collection.immutable.IndexedSeq[Int]]((
(x$1: (Int, Int)) => (x$1: (Int, Int) #unchecked) match {
case (_1: Int, _2: Int)(Int, Int)((i # _), (x # _)) => x
}))(immutable.this.IndexedSeq.canBuildFrom[Int]);
private[this] val x2: scala.collection.immutable.IndexedSeq[Int] =
scala.this.Predef.intWrapper(1).to(5).map[Int, scala.collection.immutable.IndexedSeq[Int]](((i: Int) => {
val x: Int = i.*(2);
x
}))(immutable.this.IndexedSeq.canBuildFrom[Int]);
This can be simplified to:
val x1 = (1 to 5).map {i =>
val x: Int = i * 2
(i, x)
}.map {
case (i, x) => x
}
val x2 = (1 to 5).map {i =>
val x = i * 2
x
}
Instantiating variables inside for loops makes sense if you want to use that variable the for statement, like:
for (i <- is; a = something; if (a)) {
...
}
And the reason why your list is outdated, is that this translates to a foreach call, such as:
term_array.foreach {
term => val list= hashmap.get(term)
} foreach {
...
}
So when you reach ..., your hashmap has already been changed. The other example translates to:
term_array.foreach {
term => val list= hashmap.get(term)
...
}

Why do I get "pattern type is incompatible with expected type"?

I came across with an error on my Scala code that I cannot solve by myself (I am new at Scala).
I have the following code:
def myFunction(list: List[Any]): String = {
var strItems : String = "";
list.foreach(item => {
strItems += item match {
case x:JsonSerializable => x.toJson()
case y:String => ("\"" + y + "\"")
case _ => item.toString
}
if(item != list.last)
strItems += ",";
})
strItems;
}
The error I am getting is:
error: pattern type is incompatible with expected type;
found : String
required: Unit
case y:String => ("\"" + y + "\"")
Any idea why?
PS: is there a more performant way to code myFunction
In terms of the original question, the code doesn't compile because it requires parentheses around the match, ie. strItems += (item match { ... })
A more "functional" way of writing this could be something along the lines of:
def myFunction(list:List[Any]):String = {
val strings:List[String] = list.map{
case x:JsonSerializable => x.toJson()
case y:String => ("\"" + y + "\"")
case z => z.toString
}
strings.mkString(",")
}
You could probably use a view to make it lazy and more "performant", although I don't know off the top of my head if that would combine the two underlying loops (map & mkString) into a single traversal.
Here's a form of your code that compiles (w/o any definition for JsonSerializable) (in Scala 2.8) along with a more succinct formulation (that also happens to be point-free):
object Javier01 {
def
javFunc(list: List[Any]): String = {
val strItems = new StringBuilder()
list.foreach { item =>
strItems.append ( item match {
// case x: JsonSerializable => x.toJson()
case y: String => "\"" + y + "\""
case _ => item.toString
} )
if (item != list.last)
strItems.append(",")
}
strItems.toString
}
def
rrsFunc(anys: List[Any]): String =
anys map {
// case x: JsonSerializable => x.toJson()
case s: String => "\"" + s + "\""
case x => x.toString
} mkString ","
def
main(args: Array[String]): Unit = {
val stuff = List(true, 1, 123.456, "boo!")
printf(" stuff : %s%njavFunc(stuff): %s%nrrsFunc(stuff): %s%n%n",
stuff, javFunc(stuff), rrsFunc(stuff))
}
}
The output from running this is:
% scala Javier01
stuff : List(true, 1, 123.456, boo!)
javFunc(stuff): true,1,123.456,"boo!"
rrsFunc(stuff): true,1,123.456,"boo!"