Reputation: 8711
I'm trying to convert a chained map() with for-comprehension, but getting error
println("Citi names concatenated by country code")
println("Method1")
orec.groupBy( x => x.ccode ).mapValues( x => x.map( a => a.cityname).mkString("[",",","]")).take(5).foreach(println)
println("Method2")
The below code throws error
var i = 0
for{
(key,value) <- orec.groupBy( x => x.ccode )
cities = value.map( a=> a.cityname)
cities2 = cities.mkString("[",",","]")
i=i+1
if(i<5) {
_ = println(key + "->" + cities2)
}
} yield ()
Error message:
Error:(49, 10) recursive value i needs type
i=i+1
Error:(50, 11) value < is not a member of Any
if(i<5)
How to solve this using immutable way?. Still, I can't figure out how to translate the take(5)
in my map() version to for-comprehension.
Upvotes: 0
Views: 466
Reputation: 39577
You're mistaking "midstream assignment" for assignment to your var i
.
The syntax used to require val
:
scala> for (i <- List(42) ; val j = i + 1) yield j
^
warning: `val` keyword in for comprehension is deprecated: instead, bind the value without `val`
res3: List[Int] = List(43)
scala> val i = i + 1
^
error: recursive value i needs type
It's more usual to keep the take
, but improving on the other answer:
scala> for {
| ((key, value), index) <- orec.groupBy( x => x.ccode ).zipWithIndex
| cities2 = value.map( a=> a.cityname).mkString("[",",","]")
| if index < 5
| } println(key + "->" + cities2)
fr->[paris,lille,bordeaux]
us->[ny]
de->[berlin]
en->[london]
be->[gantt]
or
scala> for {
| (key, value) <- orec.groupBy(_.ccode)
| } yield (key, value.map(_.cityname).mkString("[",",","]"))
res4: scala.collection.immutable.Map[String,String] = HashMap(fr -> [paris,lille,bordeaux], us -> [ny], de -> [berlin], en -> [london], be -> [gantt], austria -> [vienna])
scala> .take(5).foreach { case (k,v) => println(s"$k -> $v") }
fr -> [paris,lille,bordeaux]
us -> [ny]
de -> [berlin]
en -> [london]
be -> [gantt]
or
scala> val it = orec.groupBy(_.ccode).mapValues(_.map(_.cityname).mkString("[",",","]")).iterator
^
warning: method mapValues in trait MapOps is deprecated (since 2.13.0): Use .view.mapValues(f). A future version will include a strict version of this method (for now, .view.mapValues(f).toMap).
it: Iterator[(String, String)] = <iterator>
scala> for ((k, v) <- it.take(5)) println(s"$k -> $v")
fr -> [paris,lille,bordeaux]
us -> [ny]
de -> [berlin]
en -> [london]
be -> [gantt]
Upvotes: 1
Reputation: 6099
To replace your take(5)
, you could use an if on the index, to generate the index, you can use zipWithIndex
If you want to increment a var
in scala, you need to specify the type of the var. (Here Int
)
So this is the code you might be looking for
case class City(ccode: String, cityname: String)
val orec: Seq[City] = Seq(City("fr", "paris"), City("fr", "lille"), City("fr", "bordeaux"), City("en", "london"), City("be", "gantt"), City("de", "berlin"), City("austria", "vienna"), City("us", "ny"))
for (((key, value), index) <- orec.groupBy( x => x.ccode ).zipWithIndex){
val cities = value.map( a=> a.cityname)
val cities2 = cities.mkString("[",",","]")
if (index<5)
println(key + "->" + cities2)
}
Upvotes: 1