I have a list. I want to check that it contains an element of certain type, but not element of another type. Is this a idiomatic way:
myList.contains(NeededClass) && !myList.contains(NotNeededClass)
CodePudding user response:
I guess you may do this:
implicit class ListOps[A](private val list: List[A]) extends AnyVal {
def containsType[B <: A](implicit ev: ClassTag[B]): Boolean
list.exists {
case _: B => true
case _ => false
}
}
myList.containsType[NeededClass] && !myList.containsType[NotNeededClass]
Disclaimer: Since this is a class check and not a type check, it is prone to errors due to type erasure.
CodePudding user response:
contains takes an exemplar object, you want a function that takes a predicate.
myList.exists(_.isInstanceOf[NeededClass])
&& myList.forall(_.isInstanceOf[NotNeededClass] != true)
Of course that traverses the list twice. We can traverse once, at the cost of much less readable code.
val (c1, c2) = myList.foldLeft((0, 0))((b, a)
=> (b._1 if (a.isInstanceOf[NeededClass]) 1 else 0,
b._2 if (a.isInstanceOf[NotNeededClass]) 1 else 0))
c1 >= 1 && c2 == 0