F#:从自定义列表中删除元素

时间:2016-09-10 21:45:33

标签: f#

这是一个定义的列表:

 type ilist = 
        E
       | L of int * ilist

其中构造函数E代表空列表,构造函数L通过在另一个列表前添加数字来构建列表。

然后可以用一个顺序表示一个元素为1,4,6,7的列表,其中ilist值为:L(1,L(4,L(6,L(7,E)) ))

现在我需要实现一个remove()函数来从列表中删除元素的所有出现。例如,删除2(L(1,L(2,L(3,L(3,L(2,E))))))是L(1,L(3,L(3,E)))

这是我的解决方案:

let rec remove (x:int) (l:list)=
    match (x, l) with
    | (_, E)->E
    | (_, L(x, l1)) -> remove (x) (l1)
    | (_, L(y, l1)) -> L(y, remove (x)(l1)) // Warning: This line will never be matched

如您所见,第三种情况永远不会匹配。我如何处理这种情况,以便我可以在列表中维护元素,如果它不是x?

正确的解决方案:

let rec remove (x:int) (l:ilist) =
    match l with
    | E->E
    | L(y, l1) when x==y -> remove x  l1
    | L(y, l1) -> L(y, remove x l1)

1 个答案:

答案 0 :(得分:3)

非常宽松地说,在模式匹配中,你给匹配语句后面的东西一个新名称。 match (x, l)表示:你接受你的论点,分解它们,分配新的名字。在你的第二个匹配子句中,你基本上说:忽略元组的第一部分。对于列表,请为head元素指定名称x,其余为名称l1。现在,这个新名称x会影响你的论点x。特别是,这不被解释为“如果列表的第一个元素是x,那么就......”

这也解释了为什么你的第三个匹配子句永远不会匹配:你是否给头元素命名为xy并不重要 - 它匹配相同类型的列表。

另请注意,所有匹配条款都有_,您可以更改为match l with并删除所有_。你所追求的是像

match l with
| E -> E
| L(head, rest) when head = x -> rest
| L(head, rest) -> L(head, remove x rest)

这里也是一个非常好的article about pattern matching.