Во-первых, вы хотите split
вернуть пару списков, поэтому тип возвращаемого значения должен быть (List[Int], List[Int])
. Однако работа с парами и списками может часто означать частое разложение возвращаемых значений. Возможно, вам понадобится вспомогательная функция для тяжелого подъема.
Например, вашей вспомогательной функции могут быть предоставлены два списка, изначально пустые, и создавать содержимое до тех пор, пока первый список не станет пустым. Тогда результатом будет пара списков.
Следующее, что вам нужно решить в своем рекурсивном дизайне функций, - «Каково главное решение?». В вашем случае это значение «не больше, чем p». Это приводит к следующему коду:
def split(p:Int, xs: List[Int]): (List[Int], List[Int]) = {
def splitAux(r: List[Int], ngt: List[Int], gt: List[Int]): (List[Int], List[Int]) =
r match {
case Nil => (ngt, gt)
case head :: rest if head <= p =>
splitAux(rest, head :: ngt, gt)
case head :: rest if head > p =>
splitAux(rest, ngt, head :: gt)
}
val (ngt, gt) = splitAux(xs, List(), List())
(ngt.reverse, gt.reverse)
}
Шаг реверсирования не является абсолютно необходимым, но, вероятно, является наименее удивительным. Аналогичным образом, второй защитный предикат делает явным путь, который делается.
Однако существует гораздо более простой способ: использовать встроенную функциональность.
def split(p:Int, xs: List[Int]): (List[Int], List[Int]) = {
(xs.filter(_ <= p), xs.filter(_ > p))
}
filter
извлекает только те предметы, которые соответствуют критерию. Это решение просматривает список дважды, но поскольку у вас есть шаг reverse
в предыдущем решении, вы все равно это делаете.
Вы понимаете алгоритм? – justanothercoder
Если вы хотите сделать это рекурсивно, то внутри вашей функции введите вспомогательную функцию подписи splitHelper (p: Int, input: List, more: List, noGreater: List): (List, List). Очевидно, что List [Int] повсюду. Вспомогательная функция может только вызывать себя или возвращать результат. Реализуйте свою основную функцию, позвонив: splitHelper (p, xs, Nil, Nil) – ponythewhite