簡體   English   中英

不遞歸地從列表中刪除連續的重復項

[英]Removing consecutive duplicates from a list without recursion

我應該從int list中刪除連續的重復項而不使用遞歸並且只使用List.foldmapfilterfold_leftfold_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_leftList.consFun.flip輕松地重新實現它。

let rev lst = 
  List.fold_left (Fun.flip List.cons) [] lst

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM