Я просто прочитал this thread и нашел интересным.OCaml: Удаление дубликатов из списка при сохранении порядка справа
Я реализовать remove from the left
функцию в течение нескольких минут:
(*
* remove duplicate from left:
* 1 2 1 3 2 4 5 -> 1 2 3 4 5
* *)
let rem_from_left lst =
let rec is_member n mlst =
match mlst with
| [] -> false
| h::tl ->
begin
if h=n then true
else is_member n tl
end
in
let rec loop lbuf rbuf =
match rbuf with
| [] -> lbuf
| h::tl ->
begin
if is_member h lbuf then loop lbuf tl
else loop (h::lbuf) rbuf
end
in
List.rev (loop [] lst)
Я знаю, что я мог бы реализовать is_member
по Map
или hashtable
, чтобы сделать это быстрее, но в этот момент, что это не моя забота.
В случае реализации remove from the right
, я могу реализовать его List.rev
:
(*
* remove duplicate from right:
* 1 2 1 3 2 4 5 -> 1 3 2 4 5
* *)
let rem_from_right lst =
List.rev (rem_from_left (List.rev lst))
Я интересно, если мы можем реализовать это по-другому?
Это кажется очень сложным и неэффективным решением. Почему бы не пересечь список справа налево, а не слева направо? –
@AaditMShah: 'fold' определенно лучше, OTOH это ближе к тому, что OP было так поучительно, и это показывает, что некоторых минимальных изменений достаточно, чтобы заставить программу работать. +1 к вашему ответу тоже. –
Ну, функция 'is_member' - это только функция' List.mem', а функция 'loop' похожа на функцию' List.fold_left'. Нет необходимости изобретать колесо, если вы не хотите понять, как работает колесо. –