Reputation: 4481
I got a weird exception in this snippet
val splitted = "This is a text that to test something".split("\\,|\\ ")
val map = mutable.Map[Int, List[String]]()
(0 to splitted.length).foreach {
case i =>map(i) = map.getOrElse(i,List[String]("")) ++ splitted(i)
}
but I have got this exception:
type mismatch;
found : List[Any]
required: List[String]
case i =>map(i) = map.getOrElse(i,List("")) ++ splitted(i)
^ ^
Upvotes: 0
Views: 1484
Reputation: 9816
Not sure what you're trying to do with that code but here's a working version:
(0 to splitted.length-1).foreach {
case i =>map(i) = (map.getOrElse(i,List[String]("")) :+ splitted(i))
}
which will create:
println(map)
Map(2 -> List(, a), 5 -> List(, to), 4 -> List(, that), 7 -> List(, something), 1 -> List(, is), 3 -> List(, text), 6 -> List(, test), 0 -> List(, This))
EDIT: Maybe what you need is the following:
splitted.zipWithIndex.map{case (s,i)=>(i,s)}.toMap
which results in:
Map(0 -> This, 5 -> to, 1 -> is, 6 -> test, 2 -> a, 7 -> something, 3 -> text, 4 -> that)
or more efficiently:
((0 to splitted.length-1) zip splitted).toMap
Upvotes: 1
Reputation: 39577
You are yet another victim of the inference of Any
.
scala> map.getOrElse(7,List[String](""))
res3: List[String] = List("")
scala> res3 ++ "abc"
res4: List[Any] = List("", a, b, c)
Here's the same thing with -Xlint
:
scala> (0 to splitted.length).foreach {
case i =>map(i) = map.getOrElse(i,List[String]("")) ++ splitted(i)
}
<console>:12: error: type mismatch;
found : List[Any]
required: List[String]
case i =>map(i) = map.getOrElse(i,List[String]("")) ++ splitted(i)
^
scala> val res3 = { map.getOrElse(7,List[String]("")) }
<console>:6: warning: Unused import
import collection.mutable
^
res3: List[String] = List("")
scala> res3 ++ "abc"
<console>:11: warning: a type was inferred to be `Any`; this may indicate a programming error.
res3 ++ "abc"
^
res1: List[Any] = List("", a, b, c)
Unfortunately, the -Xlint
warning is smothered by the error.
And, under -Xlint -Xfatal-warnings
, the warning doesn't get a chance to error out:
scala> (0 to splitted.length).foreach {
case i =>map(i) = map.getOrElse(i,List[String]("")) ++ splitted(i)
}
<console>:11: error: type mismatch;
found : List[Any]
required: List[String]
case i =>map(i) = map.getOrElse(i,List[String]("")) ++ splitted(i)
^
If the warning is not inside the closure, then you get the helpful message under -Xlint -Xfatal-warnings
:
val ss: List[String] = (null: mutable.Map[Int,List[String]]).getOrElse(0,List.empty[String]) ++ "abc"
Upvotes: 2
Reputation: 5768
splitted(i)
is a String
and ++
(which expects a collection) treats String like Array[Char]
, which then results in the common supertype List[Any]
.
Example:
val list = List("a", "b") ++ "hello"
println(list) //prints List(a, b, h, e, l, l, o) and is of type List[Any]
If it doesn't matter where it's inserted then i would do it like this:
case i => map(i) = splitted(i) :: map.getOrElse(i,List[String](""))
If it should be appended:
case i => map(i) = map.getOrElse(i,List[String]("")) :+ splitted(i)
Upvotes: 2
Reputation: 20285
This works.
val splitted = "This is a text that to test something".split("\\,|\\ ")
val map = scala.collection.mutable.Map[Int, List[String]]()
(0 until splitted.length).foreach {
case i =>map(i) = map.getOrElse(i,List[String]("")) :+ splitted(i)
}
Which outputs:
scala.collection.mutable.Map[Int,List[String]] = Map(2 -> List("", a), 5 -> List("", to), 4 -> List("", that), 7 -> List("", something), 1 -> List("", is), 3 -> List("", text), 6 -> List("", test), 0 -> List("", This))
Also, note the difference between to
and until
. Using to
in will give and ArrayOutOfBoundsException
.
scala> val l = List(1,2,3)
l: List[Int] = List(1, 2, 3)
scala> 0 to l.length
res51: scala.collection.immutable.Range.Inclusive = Range(0, 1, 2, 3)
scala> 0 until l.length
res52: scala.collection.immutable.Range = Range(0, 1, 2)
Upvotes: 0