列表模式匹配添加基于案例对象的过滤

List pattern matching add filtering based on case object

我有一个要迭代的男性和女性居民列表。

如何在列表模式匹配中添加基于性别的过滤? (只有当居民性别为 MalecountOldManFloor 才会 return 1,因此 countOldManFloor(inhabitantsFemale) 会 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))

Online code

我试过 case inhabitant: Male :: inhabitants if inhabitant.age > olderThen => 1= inhabitants.filter() match {} 但没用

我了解到您需要的是 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)
  }

您可以在模式中匹配模式。在这种情况下,Male 模式,在 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, ageLimit, acc)
  case Nil     => acc
}

countOldManFloor(inhabitantsBoth, olderThan)    // 1
countOldManFloor(inhabitantsMale, olderThan)    // 2
countOldManFloor(inhabitantsFemale, olderThan)  // 0

请注意,我将 olderThan 设为传递参数。在定义之外引用变量的方法 space 是一种代码味道。

您的方法无效,因为您没有添加任何东西,只能返回 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
}

Scastie

我认为你可以只用 count 而不是任何递归来做到这一点:

def countOldManFloor(inhabitants: List[Inhabitant]): Int = 
  inhabitants.count(inhabitant => inhabitant.age > olderThan && inhabitant.gender == Male)

Scastie