I want to find in some Iterable some elements that both conform to some given type, and validates a predicate taking that type as an argument.
I wrote this method using imperative-style programming, which seems to conform to my expectations. Is there some way to write this in a more "scalaesque" way?
def findMatch[T](it: Iterable[_], clazz: Class[T], pred: T => Boolean): Option[T] = {
val itr = it.iterator
var res: Option[T] = None
while (res.isEmpty && itr.hasNext) {
val e = itr.next()
if (clazz.isInstance(e) && pred(clazz.cast(e))) {
res = Some(clazz.cast(e))
}
}
res
}
You can use collect
if you want to find
and then map
.
scala> val it: Iterable[Any] = List(1,2,3,"4")
it: Iterable[Any] = List(1, 2, 3, 4)
scala> it.view.collect{case s: String => s}.headOption
res1: Option[String] = Some(4)
You can work with an existantial type X forSome{typeX}
rather than using _
as type parameter. This then would enable you to write it with the mentioned find method and use the map method on the Option type:
def findMatch[T](it: Iterable[X forSome {type X}], clazz: Class[T], pred: T => Boolean): Option[T] = {
it.find{ e => clazz.isInstance(e) && pred(clazz.cast(e))}.map{clazz.cast(_)}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With