问题描述
我有一个要迭代的男女居民列表。
如何在列表模式匹配中添加基于性别的过滤? (这样,countOldManFloor
仅在居民性别为Male
时返回1,结果countOldManFloor(inhabitantsFemale)
会返回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))
我尝试了case inhabitant: Male :: inhabitants if inhabitant.age > olderThen => 1
和= inhabitants.filter() match {}
,但是没有用
解决方法
您可以在模式中匹配模式。在这种情况下,Male
的{{1}}模式中的Inhabitant()
模式中的::
模式。
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,acc)
case Nil => acc
}
countOldManFloor(inhabitantsBoth,olderThan) // 1
countOldManFloor(inhabitantsMale,olderThan) // 2
countOldManFloor(inhabitantsFemale,olderThan) // 0
设置了传递参数。在定义空间之外引用变量的方法是代码的味道。
我知道您需要的是30岁以上的男性计数器,因此我添加了性别状况检查。
def countOldManFloor(inhabitants: List[Inhabitant]): Int = {
def checkGender(inhabitant: Gender): Boolean = inhabitant match {
case Male => true
case _ => false
}
@tailrec
def loop(lst: List[Inhabitant],cont: Int): Int = {
lst match {
case Nil => cont
case (h :: tail) if h.age > olderThen && checkGender(h.gender) => loop(tail,cont + 1)
case _ => loop(lst.tail,cont)
}
}
loop(inhabitants,0)
}
,
您的方法无效,因为您未添加任何内容,只能返回1和0。如果您不关心尾递归,则可能会起作用:
def countOldManFloor(inhabitants: List[Inhabitant]): Int = inhabitants match {
case Inhabitant(age,Male) :: inhabitants if age > olderThan => countOldManFloor(inhabitants) + 1
case inhabitant :: inhabitants => countOldManFloor(inhabitants)
case Nil => 0
}
我认为您可以只使用count
来执行此操作,而不必执行任何递归操作,
def countOldManFloor(inhabitants: List[Inhabitant]): Int =
inhabitants.count(inhabitant => inhabitant.age > olderThan && inhabitant.gender == Male)