Начнем с обозначения типа функции. Так как он получает n
и список в качестве аргументов и возвращает пару списков, у вас есть функция split
:
val split : int -> 'a list -> 'a list * 'a list
Вот один подход к реализации этой функции:
let split n xs =
let rec splitUtil n xs acc =
match xs with
| [] -> List.rev acc, []
| _ when n = 0 -> List.rev acc, xs
| x::xs' -> splitUtil (n-1) xs' (x::acc)
splitUtil n xs []
Идея с использованием аккумулятор acc
, чтобы удерживать элементы, которые вы прошли и уменьшились n
длинный путь. Поскольку элементы добавляются к acc
, в конце вы должны отменить его, чтобы получить правильный порядок.
Функция имеет два базовых случая к прекращению:
- Там не осталось, чтобы пересечь элемент (
xs = []
в этой точке).
- Вы прошли первые
n
элементов в списке (n
уменьшено до 0
в это время).
Вот краткий пример того, как split
вычисляет результат:
split 2 [1; 2; 3] // call the auxiliary function splitUtil
~> splitUtil 2 [1; 2; 3] [] // match the 3rd case of x::xs'
~> splitUtil 1 [2; 3] [1] // match the 3rd case of x::xs'
~> splitUtil 0 [3] [2; 1] // match the 2nd case of n = 0 (base case)
~> List.rev [2; 1], [3] // call List.rev on acc
~> [1; 2], [3]
Что вы пробовали?По крайней мере, вы должны дать нам нерабочую версию, чтобы показать свои усилия? – pad
Подсказка: вам не нужно выражать длину списка - все, что вам нужно, это способ уменьшить «n» и проверить, достигло ли оно нуля. – dasblinkenlight
Это может быть немного не по теме, но было довольно аккуратное решение (Джульетта), которое разбило список на две половины, не зная/указав длину заранее: http://stackoverflow.com/questions/4866640/split- list-into-two-equal-lists-in-f –