【问题标题】:List pattern matching add filtering based on case object列表模式匹配添加基于案例对象的过滤
【发布时间】:2021-01-17 19:24:42
【问题描述】:

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

如何在列表模式匹配中添加基于性别的过滤? (这样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))

Online code

我尝试了case inhabitant: Male :: inhabitants if inhabitant.age > olderThen => 1 和= inhabitants.filter() match {},但没有成功

【问题讨论】:

  • 嗨@techkuz,您想通过Gender 和age 进行检查,还是两者兼而有之?我不明白。
  • 嗨@Chema。两者,我只需要计算年龄过滤的男性
  • 嗨@techkuz,如果我没记错的话,结果将是30岁以上的男性。

标签: scala functional-programming pattern-matching tail-recursion


【解决方案1】:

您可以在模式中匹配模式。在这种情况下,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 设为传递参数。在定义空间之外引用变量的方法是代码异味。

【讨论】:

    【解决方案2】:

    我知道您需要的是 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)
      }
    

    【讨论】:

      【解决方案3】:

      您的方法不起作用,因为您没有添加任何内容,只能返回 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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-19
        • 2012-01-02
        • 2015-05-15
        • 2012-04-11
        • 2015-04-27
        • 1970-01-01
        相关资源
        最近更新 更多