-2

Given a List of Any:

val l = List(2.9940714E7, 2.9931662E7, 2.993162E7, 2.9931625E7, 2.9930708E7, 2.9930708E7, 2.9931477E7)

I need to cast each item to Int.

Works:

l(1).asInstanceOf[Double].toInt

Not:

l.foreach{_.asInstanceOf[Double].toInt}
> java.lang.String cannot be cast to java.lang.Double

If

l.foreach{_.asInstanceOf[String].toDouble.toInt}
> java.lang.Double cannot be cast to java.lang.String

I'm new to Scala. Please tell me what I'm missing. Why I can cast one item from list, but can't do this via iterator? Thanks!

Xavier Guihot
  • 54,987
  • 21
  • 291
  • 190

2 Answers2

3

Your given List is of type Double. You can use simply map operation to convert it to Int type. try following code,

val l: List[Double] = List(2.9940714E7, 2.9931662E7, 2.993162E7, 2.9931625E7, 2.9930708E7, 2.9930708E7, 2.9931477E7)

//simply map the list and use toInt
val intLst: List[Int] = l.map(_.toInt)

print(intLst)

//output
//List(29940714, 29931662, 29931620, 29931625, 29930708, 29930708, 29931477)

But suppose you have same List as List[Any] instead then you can use following to convert it to Int.

val l: List[Any] = List(2.9940714E7, 2.9931662E7, 2.993162E7, 2.9931625E7, 2.9930708E7, 2.9930708E7, 2.9931477E7)

val intLst: List[Int] = l.map(_.asInstanceOf[Double].toInt)

It will give same output as above.

vindev
  • 2,240
  • 2
  • 13
  • 20
3

It seems as if a String somehow ended up in your List l.

Given a list that is structured like this (with mixed integers, Doubles, and Strings):

val l = List[Any](2.9940714E7, 2.9931625E7, "2.345E8", 345563)

You can convert it to list of integers as follows:

val lAsInts = l.map {
  case i: Int => i
  case d: Double => d.toInt
  case s: String => s.toDouble.toInt
}

println(lAsInts)

This works for Doubles, Ints and Strings. If it still crashes with some exceptions during the cast, then you can add more cases. You can, of course, do the same in a foreach if you want, but in this case it wouldn't do anything, because you don't do anything in the body of foreach except casting. This has no useful side-effects (e.g. it prints nothing).

Another option would be:

lAsInts = l.map{_.toString.toDouble.toInt}

This is in a way even more forgiving to all kind of weird input, at least as long as all values are "numeric" in some sense.

However, this is definitely code-smell: how did you get a list with such a wild mix of values to begin with?

Andrey Tyukin
  • 43,673
  • 4
  • 57
  • 93
  • It's a very long story. I have some json with numerous properties in different types. I've extracted that data from Redis, parsed with scala.util.parsing.json._ it returned Map[String, Any] but it turned values with type String like "29940714" to Any 2.9940714E7 after parsing. And I afterwards I map obtained Map with case class to have ojects with necessary data then filter by some properties. Anyways _.toString.toDouble.toInt worked fine. Thanks a lot! – shotgunVSspell Feb 12 '18 at 14:22