Reputation: 3709
Scala: Detect and extract something more specific from a collection of Any
values.
(Motivation: The Saddle library -- the only Scala library I have found that provides a Frame type, which is critical for data science -- leads me to this puzzle. See last section for details.)
Imagine a collection c
of type C[Any]
. Suppose that some of the elements of c
are of a type T
which is strictly more specific than Any
.
I would like a way to find all the elements of type T
, and to then create an object d
of type C[T]
, rather than C[Any]
.
scala> val c = List(0,1,"2","3")
<console>:11: warning: a type was inferred to be `Any`;
this may indicate a programming error.
val c = List(0,1,"2","3")
^
c: List[Any] = List(0, 1, 2, 3)
scala> :t c(0)
Any // I wish this were more specific
// Scala can convert some elements to Int.
scala> val c0 = c(0) . asInstanceOf[Int]
c0: Int = 0
// But how would I detect which?
scala> val d = c.slice(0,2)
d: List[Any] = List(0, 1) // I wish this were List[Int]
Saddle lets you manipulate "Frames" (tables). Frames can have columns of various types. Some systems (e.g. Pandas) assign a separate type to each column. Every Frame in Saddle, however, has exactly three type parameters: The type of row labels, the type of column labels, and the type of cells.
Real world data is typically a mix of strings and numbers. The way such tables are represented in Saddle is as a Frame with a cell type of Any. I'd like to downcast (upcast? polymorphism is hard) a column to something more specific than a Series of Any values. I'd also like to be able to test a column, to be sure that the cast is appropriate.
I posted an issue on Saddle's Github site about the puzzle.
Upvotes: 0
Views: 61
Reputation: 19987
You could do something like this
scala> val c = List(0,1,"2","3")
c: List[Any] = List(0, 1, 2, 3)
scala> c.collect { case x: Int => x; case s: String => s.toInt }
res0: List[Int] = List(0, 1, 2, 3)
If you just want the Int
types you can simply drop the second case.
Upvotes: 1