2

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

我试图编写一个以 aList[(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

有什么建议么?

4

2 回答 2

2

错误是您在每个 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
  }
}

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

case x => x

应该:

case x :: Nil => x :: Nil

否则 x 会匹配任何东西。这也使您有可能删除案例:

case Nil => Nil

如果您不想删除 case x => x

于 2016-11-04T11:02:32.627 回答
0

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

  }

casecase x => x将匹配列表 Nil 案例和具有一个元素案例的列表。

于 2016-11-04T10:49:35.280 回答