问题描述
我是F#世界的初学者。我有一个关于删除列表中项目的问题。 假设您有一个任意列表,可以说
let list1 = [0;1;2;0;3;4;0;0]
我想删除所有最后的零,以便列表变为
list1 = [0;1;2;0;3;4]
我尝试过反转列表,然后检查头是否为零,然后递归调用尾部
let rec remove ps = if List.rev(ps).Head <> 0 then ps else remove(ps.Tail);;
但是我要么以一个空列表的错误代码结尾,要么它只是返回原始列表。
非常感谢您的帮助
解决方法
您的“虫子”是这个。首先,您反转列表,所以:
[0;0;4;3;0;2;1;0]
然后检查它是否以0
开头-确实如此。然后,您通过原始列表的结尾 。因此,您删除了第一个数字,而不是最后一个:
[1;2;0;3;4;0;0]
由于您永远不会删除最后一个零,因此在测试true
时它将返回0
,直到您最终用空列表调用remove
为止。然后,您将引发异常,试图获取空列表的Head
。
这修复了该错误,以反向列表的末尾(因此没有最后一个数字)递归调用,再次反向恢复了原始顺序:
let rec remove ps =
let reversed = List.rev ps
if reversed.Head <> 0 then ps else remove (List.rev reversed.Tail)
使用模式匹配可能更惯用。这也不会抛出空列表:
let rec remove list =
match List.rev list with
| 0::xs -> remove (List.rev xs)
| _ -> list
您也可以执行相同的操作而无需递归。反转列表一次,跳过直到值不为0
,然后再次反转:
let remove list =
list
|> List.rev
|> List.skipWhile (fun x -> x = 0)
|> List.rev