我是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
。
有什么建议吗?
错误是您在每个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
如果你不想删除大小写x => x
x后面的额外类型注释是不必要的,也是错误的。
remove this
(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 case x => x
将匹配list Nil case和list只有一个元素case。