我嘗試通過迭代一個帶有空串列的串列來為這個練習撰寫自己的解決方案,在該complst
串列中插入所有非重復項,然后回傳。在查找解決方案后,我知道這是一種過于復雜的方法,但仍然想了解為什么模式匹配不能按預期作業:
let compress list =
let rec aux complst lst =
match lst with
| [] -> complst
| a :: (b :: c) -> if a = b then aux complst (b::c) else aux (a::complst) (b::c)
| x -> x
in aux [] list;;
val comp : 'a list -> 'a list = <fun>
不管輸入如何,輸出總是一個只有最后一個元素的串列:
compress [1;1;2;2;3];;
- : int list = [3]
compress [1;2;3];;
- : int list = [3]
uj5u.com熱心網友回復:
模式匹配
您的模式匹配與三種模式匹配:
- 空串列:
[]
- 至少包含兩個元素的串列:
a :: (b :: c)
- 一個包羅萬象的東西,它必須通過消除程序成為一個具有單個元素的串列。
考慮當我們評估您的示例時會發生什么:
compress [1; 1; 2; 2; 3]
aux [] [1; 1; 2; 2; 3]
aux [] [1; 2; 2; 3]
aux [1] [2; 2; 3]
aux [1] [2; 3]
aux [2; 1] [3]
[3]
lst
哎呀,一旦它擊中[3]
它就回傳它。
讓我們通過添加來重寫您的函式以處理該單個元素串列complst
。
let compress lst =
let rec aux complst lst =
match lst with
| [] -> complst
| [x] -> aux (x::complst) []
| a :: (b :: c) ->
if a = b then aux complst (b::c)
else aux (a::complst) (b::c)
in
aux [] list
現在:
compress [1; 1; 2; 2; 3]
aux [] [1; 1; 2; 2; 3]
aux [] [1; 2; 2; 3]
aux [1] [2; 2; 3]
aux [1] [2; 3]
aux [2; 1] [3]
aux [3; 2; 1] []
[3; 2; 1]
清理并反轉結果串列
當然,也有一些方法可以使用條件保護來稍微清理代碼,并且_
對于不需要將名稱系結到的值。您可能還想反轉您的累加器。
let compress lst =
let rec aux complst lst =
match lst with
| [] -> List.rev complst
| [x] -> aux (x::complst) []
| a :: (b :: _ as tl) when a = b -> aux complst tl
| a :: (_ :: _ as tl) -> aux (a::complst) tl
in
aux [] lst
折疊
當您看到這種一次遍歷串列一個元素并累積一個新值的模式時,您通常可以很好地將其映射到List.fold_left
.
let compress lst =
List.(
fold_left
(fun i x ->
match i with
| (x'::_) when x = x' -> i
| _ -> x::i)
[] lst
|> rev
)
因為List.fold_left
一次只能知道串列中的一個元素,所以我們作為第一個引數傳遞的函式無法知道串列中的下一個元素。但它知道累加器或“init”值。在這種情況下,這是另一個串列,我們可以模式匹配該串列。
如果它不為空并且第一個元素等于我們正在查看的當前元素,則不要將其添加到結果串列中。否則,請添加它。這也處理累加器為空的第一個元素情況。
感謝為這個問題創建尾遞回解決方案!
uj5u.com熱心網友回復:
你的代碼的問題主要是最后一部分,它對應于你的串列中有最后一個元素,所以在這里[3],你回傳帶有這個單個元素的串列。您需要做的是將其附加到 complst 中,如下所示:
let compress list =
let rec aux complst lst =
match lst with
| [] -> complst
| a :: (b :: c ) -> if a=b then aux complst (b::c) else aux (a::complst) (b::c)
| x::e -> x::complst
in aux [] list;;
val comp : 'a list -> 'a list = <fun>
現在您可以檢查給定的示例:
compress [1;1;2;2;3];;
- : int list = [3; 2; 1]
希望它可以幫助您更好地理解您的錯誤。
關于注釋的注意事項:您應該保留 [] 大小寫,因為盡管它只能在一種情況下發生,但它仍然是一個有效的輸入,這意味著它必須保留!。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/508405.html
下一篇:遞回Java方法未完全執行