[英]Removing consecutive duplicates from a list without recursion
我應該從int list
中刪除連續的重復項而不使用遞歸並且只使用List.fold
、 map
、 filter
、 fold_left
、 fold_right
。
我幾乎明白了,但我的代碼的問題是它檢查每個元素是否等於第二個元素,而不是下一個元素。
例如,如果let z = int list [3;1;4;5;5;1;1]
我的代碼將返回[3;4;5]
而不是[3;1;4;5;1]
。 我不確定如何更改它,因此filter
使用動態更改的列表參數,而不僅僅是原始參數(因此它不會每次都將每個元素與第二個元素(在本例中為 1)進行比較):
let dupe (ls: int list) : int list =
List.filter (fun x -> if List.length ls = 0 then true else if x = List.hd (List.tl xs) then false else true) ls
List.filter
的類型是這樣的:
# List.filter;;
- : ('a -> bool) -> 'a list -> 'a list = <fun>
值得注意的是,過濾器功能一次只能看到列表的一個元素。 您需要查看兩個連續的元素來決定要做什么,所以我想說List.filter
不能完成任務。
我會說,您將不得不使用map
或其中一折。 您可以使用類似的推理來確定哪個將起作用。
(我假設這是該作業應該說明的那種推理。因此,我將其保留在那里。)
無記錄
let remove = function
[] -> []
| x::tl ->
let (_,lxRes)=
List.fold_left (
fun (xPrec,lxRes) xCour ->
if xPrec=xCour then
(xCour,lxRes)
else
(xCour,lxRes@[xCour])
) (x+1,[]) (x::tl)
in
lxRes
測試:
# remove [3;1;4;5;5;1;1];;
- : int list = [3; 1; 4; 5; 1]
# remove [1;1];;
- : int list = [1]
# remove [1;1;1;1;2;2;3;4;5;5];;
- : int list = [1; 2; 3; 4; 5]
帶REC(僅供參考)
let rec remove =
function
| [] -> []
| x::[] -> x::[]
| x::y::tl ->
if x=y then remove (y::tl)
else x::remove (y::tl)
只使用List.fold_left
可能比前面的答案更簡潔一點。 當然,這會以相反的順序構建列表,因此我們需要反轉結果。
let remove lst =
List.(
lst
|> fold_left
(fun acc x ->
match acc with
| [] -> [x]
| hd::_ when x = hd -> acc
| _ -> x::acc)
[]
|> rev
)
當然,如果您不允許使用List.rev
,我們可以使用List.fold_left
、 List.cons
和Fun.flip
輕松地重新實現它。
let rev lst =
List.fold_left (Fun.flip List.cons) [] lst
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.