Вырезать список по индексу n в F#

Попытка написать рекурсивную функцию, которая будет сокращать список по n. Затем верните 2 списка. Так что, если я пройду

cut(2, [5;10;4;2;7]);;
  val it : int list * int list = ([5; 10], [4; 2; 7])

Я хотел бы получить что-то подобное.

let rec cut (n, xs) = 
        match n, xs with 
        | 0, xt -> (n, xs)
        | n, x::xt -> cut(n, xt), xs;;

Пожалуйста помоги.

2 ответа

Решение

Я приведу объяснение рекурсивной функции @MisterMetaphors.

Функция cut не является рекурсивной, но aux есть, она работает путем обратного отсчета от n и удаления элементов из заголовка списка, переданного в cut.

Скажем, вы называете вырезать, как это cut 2 [ 3; 4; 5; 7; 8 ], aux - это функция сопоставления с шаблоном, принимающая три аргумента: n, раздел 1, раздел 2. Раздел 1 начинается с пустого списка, а раздел 2 начинается с полного списка, передаваемого в cut.

Первый раз aux будет соответствовать второму предложению, затем он будет вызывать себя с аргументами (1, [3], [4; 5; 7; 8]). В следующий раз он также будет соответствовать второму предложению, теперь он вызывает себя с помощью (0, [4; 3], [5; 7; 8]). В третий и последний раз он соответствует первому предложению (n=0) и вернет кортеж, содержащий xs и ys.

Однако обратите внимание, что элементы xs расположены в обратном порядке, так как каждый элемент был добавлен (с помощью оператора cons::). Причина, по которой это делается, заключается в том, что это операция O(1) по сравнению с оператором добавления @, который в левой части равен O(n).

Поскольку xs находится в обратном порядке, последнее выражение в функции является обращением xs.

Альтернативное и немного короткое определение может быть:

let cut n xs =
    let rec aux = function
        | 0, xs, ys -> List.rev xs, ys
        | n, xs, y :: ys -> aux (n - 1, y :: xs, ys)
        | _ -> failwith "invalid arguments"
    aux (n, [], xs)

Вероятно, для достижения этого лучше объединить встроенные функции в списках или последовательностях:

let cut' (n, xs) =
    Seq.take n xs, Seq.skip n xs

Рекурсивно, ваша функция может быть определена так:

let cut (n, xs) =
    let rec aux = function
        | 0, xs, ys -> xs, ys
        | n, xs, y :: ys -> aux (n - 1, y :: xs, ys)
        | _ -> failwith "invalid arguments"
    let l, r = aux (n, [], xs)
    (List.rev l, r)
Другие вопросы по тегам