When trying to remove all Unit - ()
from a list, I tried to call toMap
.
scala> List((), ()).filter(_ != ()).toMap
It means that the type of an element in the list can't be viewed as a tuple which is required to build a Map. A Map in a sense is a collection of tuples (and more).
Illustration:
scala> List(1).toMap
<console>:8: error: Cannot prove that Int <:< (T, U).
List(1).toMap
^
scala> List(1 -> 2).toMap
res1: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2)
I can build a map from a list of tuples, but not from a list of single cardinality elements.
Maybe you mean to say .map
instead of .toMap
? ;)
Ah! Now your other question makes a little more sense. Still not sure what you're doing to produce this mixed Unit
/Tuple2
list though.
This should work:
List((), (), (3,4)).collect { case t@(_: Int, _: Int) => t }.toMap
Note that I'm using variable binding here (binding the match to t
) to return the same Tuple2 instance we matched rather than creating a new one.
By using collect
you convert the type of your list from List[Any]
to List[(Int, Int)]
, which is what toMap
wants since it's expecting some List[(A,B)]
.
Note: Although this answer should work for you, I still think your design is flawed. You'd be better off fixing the underlying design flaw rather than treating the symptoms like this.
It looks like this would be a good fit for using Scala's Option type. In this case, your sample list would become List(None, None, Some((3,4)))
, or you could write it as List(None, None, Some(3->4))
for readability (nested parenthesis like that can get confusing).
If you use Option
then the type of your list becomes List[Option[(Int, Int)]]
, which should be much nicer to deal with than a List[Any]
. To get rid of the None
entries and get the desired List[(Int,Int)]
you can just call flatten
:
List(None, None, Some(3->4)).flatten
// res0: List[(Int, Int)] = List((3,4))
List(None, None, Some(3->4)).flatten.toMap
// res1: scala.collection.immutable.Map[Int,Int] = Map(3 -> 4)
However, it would be even better if you can avoid putting the None
entries in your list in the first place. If you're producing this list using a Scala for comprehension, you could use a guard in your for expression to remove the invalid elements from the output.
All in one go:
scala> val l2 = List(1 -> 3, (), 4 -> 4, (), 9 -> 4, (), 16 -> 7)
l2: List[Any] = List((1,3), (), (4,4), (), (9,4), (), (16,7))
scala> (l2 collect { case (a, b) => (a, b) }).toMap
res4: scala.collection.immutable.Map[Any,Any] = Map(1 -> 3, 4 -> 4, 9 -> 4, 16 -> 7)
Better typed:
scala> (l2 collect { case (i: Int, j: Int) => (i, j) }).toMap
res5: scala.collection.immutable.Map[Int,Int] = Map(1 -> 3, 4 -> 4, 9 -> 4, 16 -> 7)