I have a list of Male and Female inhabitants to be iterated over.
How to add filtering based on gender to the list pattern matching? (such that countOldManFloor
would return 1 only if inhabitants gender is Male
and as a result countOldManFloor(inhabitantsFemale)
would return 0)
import scala.annotation.tailrec
trait Gender
case object Female extends Gender
case object Male extends Gender
case class Inhabitant(age: Int= 50, gender: Gender)
val olderThen = 30
val inhabitantsBoth: List[Inhabitant] = List(Inhabitant(gender=Male), Inhabitant(gender=Female))
val inhabitantsFemale: List[Inhabitant] = List(Inhabitant(gender=Female), Inhabitant(gender=Female))
val inhabitantsMale: List[Inhabitant] = List(Inhabitant(gender=Male), Inhabitant(gender=Male))
@tailrec
def countOldManFloor(inhabitants: List[Inhabitant]): Int = inhabitants match {
case inhabitant :: inhabitants if inhabitant.age > olderThen => 1
case inhabitant :: inhabitants => countOldManFloor(inhabitants)
case Nil => 0
}
println(countOldManFloor(inhabitantsBoth))
println(countOldManFloor(inhabitantsMale))
println(countOldManFloor(inhabitantsFemale))
I tried case inhabitant: Male :: inhabitants if inhabitant.age > olderThen => 1
and = inhabitants.filter() match {}
but it did not work
You can match patterns within patterns. In this case the Male
pattern, within the Inhabitant()
pattern, within the ::
pattern of a List
.
@tailrec
def countOldManFloor(inhabitants : List[Inhabitant]
,ageLimit : Int
,acc : Int = 0): Int = inhabitants match {
case Inhabitant(age,Male) :: tl if age > ageLimit =>
countOldManFloor(tl, ageLimit, acc + 1)
case _ :: tl => countOldManFloor(tl, ageLimit, acc)
case Nil => acc
}
countOldManFloor(inhabitantsBoth, olderThan) // 1
countOldManFloor(inhabitantsMale, olderThan) // 2
countOldManFloor(inhabitantsFemale, olderThan) // 0
Notice that I made olderThan
a passed parameter. Methods that reference variables outside of their definition space is a code smell.