Scala 匹配带有守卫的元组列表

Scala matching List of tuples with guards

我是 Scala 新手。作为练习,我正在尝试在带有守卫的元组列表上编写匹配语句。我知道地图可以解决问题,但我正在尝试了解模式匹配。

我试图编写一个以 List[(Char, Int)] 作为参数的函数。该函数对条目进行排序,如果两个条目具有相同的键值,则将它们相加。所以下面的参数 List(('q', 1'), ('a', 1), ('c', 2), ('a', 2), ('c', 1)) 会变成 List(('a', 3), ('c', 3'), ('q', 1))

我有以下代码:

def sortAndAggregateList(chars: List[(Char, Int)]) : List[(Char, Int)] = {
  chars match {
    case (charP1, numP1) :: (charP2, numP2) :: (x : List[(String, Int)]) if (charP1 > charP2) =>
      sortAndAggregateList((charP2, numP2) :: (charP1, numP1) :: x)
    case (charP1, numP1) :: (charP2, numP2) :: (x : List[(String, Int)]) if (charP1 < charP2) =>
      sortAndAggregateList((charP1, numP1) :: (charP2, numP2) :: x)
    case (charP1, numP1) :: (charP2, numP2) :: (x : List[(String, Int)]) if (charP1 == charP2) =>
      sortAndAggregateList((charP1, numP1 + numP2) :: x)
    case Nil =>
      Nil
  }
}

但我收到以下警告:

:14: 警告:无结果类型测试:List[(Char, Int)] 类型的值不能同时是 List[(String, Int)](List[(String, Int)] 的基础) )(但仍可能匹配其擦除)

我尝试删除列表,但如果我这样做,我会收到 x 类型 Any 的错误。

有什么建议吗?

x 之后的额外类型注释不是必需的,也是错误的。

删除此

(x : List[(String, Int)])

改为使用(非强制。你可以省略类型注释)

(x : List[(Char, Int)])

功能齐全

  def sortAndAggregateList(chars: List[(Char, Int)]): List[(Char, Int)] = chars match {
    case (charP1, numP1) :: (charP2, numP2) :: x if charP1 > charP2 =>

      sortAndAggregateList((charP2, numP2) :: (charP1, numP1) :: x)

    case (charP1, numP1) :: (charP2, numP2) :: x if charP1 < charP2 =>

      sortAndAggregateList((charP1, numP1) :: (charP2, numP2) :: x)

    case (charP1, numP1) :: (charP2, numP2) :: x if charP1 == charP2 =>

      sortAndAggregateList((charP1, numP1 + numP2) :: x)

    case x => x
  }

如果您考虑折叠元组,代码会更清晰

  def sortAndAggregateList(chars: List[(Char, Int)]): List[(Char, Int)] = chars match {
    case a :: b :: x if a._1 > b._2 =>

      sortAndAggregateList(b :: a :: x)

    case a :: b :: x if a._1 < b._1 =>

      sortAndAggregateList(a :: b :: x)

    case a :: b :: x if a._1 == b._1 =>

      sortAndAggregateList((a._1, (a._2 + b._2)) :: x)

   case x => x

  }

大小写 case x => x 将匹配列表 Nil 大小写和具有一个元素大小写的列表。

错误是您在每个 case 语句之后进行的类型检查 (: List[(String, Int)])。

如果您将代码更改为以下错误消失:

def sortAndAggregateList(chars: List[(Char, Int)]) : List[(Char, Int)] = {
  chars match {
    case (charP1, numP1) :: (charP2, numP2) :: x if (charP1 > charP2) =>
      sortList(p1 :: p2 :: x)
    case (charP1, numP1) :: (charP2, numP2) :: x if (charP1 < charP2) =>
      sortList(p2 :: p1 :: x)
    case (charP1, numP1) :: (charP2, numP2) :: x if (charP1 == charP2) =>
        val p3: (Char, Int) = (charP1, numP1 + numP2)
        sortList(p3 :: x)
    case x =>
      x
    case Nil =>
      Nil
  }
}

之后你会发现编译器告诉你p1和p2是未定义的。要解决此问题,您需要将它们设置为 p1 = (charP1, numP1) 和 p2 = (charP2, numP2)。 要使用您的语法解决此问题,您可以执行以下操作:

def sortAndAggregateList(chars: List[(Char, Int)]) : List[(Char, Int)] = {
  chars match {
    case (charP1, numP1) :: (charP2, numP2) :: x if (charP1 > charP2) =>
      sortList((charP1, numP1) :: (charP2, numP2) :: x)
    case (charP1, numP1) :: (charP2, numP2) :: x if (charP1 < charP2) =>
      sortList((charP2, numP2) :: (charP1, numP1) :: x)
    case (charP1, numP1) :: (charP2, numP2) :: x if (charP1 == charP2) =>
        val p3: (Char, Int) = (charP1, numP1 + numP2)
        sortList(p3 :: x)
    case x =>
      x
    case Nil =>
      Nil
  }
}

现在唯一缺少的 link 是您尚未添加的 sortList 函数。 我不确定这是否可行,因为我认为是这样的:

case x => x

应该是:

case x :: Nil => x :: Nil

否则 x 将匹配任何内容。这也让您有可能删除案例:

case Nil => Nil

如果您不想删除大小写 x => x