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.

Другие вопросы по тегам