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
,
Какие-либо предложения?
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
если вы не хотите удалить случай x => x
Дополнительная аннотация типа после 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 и списку, имеющему один элемент case.