删除F#中的尾部项目

问题描述

我是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