F#相交两个列表

时间:2017-10-12 11:46:28

标签: f#

所以我想要交叉两个排序列表,这样intersect ([1;1;1;2;2], [1;1;2;4])将返回[1;1;2]。我走到这一步:

let rec intersect (xs, xs') =
    match xs, xs' with
    | ([], [])             -> []
    | (x::tail, [])        -> []
    | ([], x'::tail')      -> []
    | (x::tail, x'::tail') -> if x = x' then x::intersect(tail, tail')
                              else intersect(tail, xs') 

但我不太确定从哪里开始。该函数采用包含两个列表的元组,我假设当每个列表的头部彼此相等时,我开始建立一个新列表,但我遗漏了一些我无法弄清楚的东西,并希望得到一个提示。

编辑:我知道我可以使用库函数来轻松解决这个问题,但这并不好玩:)

2 个答案:

答案 0 :(得分:4)

以下是我提出的建议:

let rec intersect xs ys =
    match xs, ys with
    | x::xs', y::ys' ->
        if   x = y then x :: intersect xs' ys'
        elif x < y then intersect xs' ys
        else            intersect xs  ys'
    | _ -> []

我删除了参数的元组,因为我没有理由这样做。

x::xs'只会与非空列表匹配,因此基本案例匹配可以移到最后并简化为_

我也更改了名字。我发现最好只在引用已存在值的下一次迭代的名称中使用tick后缀。在这种情况下,您有一个列表xs,其尾部为xs'

答案 1 :(得分:2)

我建议您将参数重命名为l1l2,并与(x :: xs)(y :: ys)匹配,即

let rec intersect (l1, l2) =
    match l1,l2 with
    ...
    | (x :: xs), (y :: ys) when x < y -> 

你遗漏的两个案例是两个头不同的地方,即x < yx > y。如果x < y,那么由于列表已排序,l2前面有一个或多个元素可以忽略,因为它们不能存在于l1中,例如x = 5。如果

l2 = [1;2;4;5][1;2;4]然后//removes items from the front of l which cannot occur in a sorted list with head e let rec skipUntil e l = ... 可以被丢弃以找到下一场比赛。

我建议你写一个实用函数,它会丢弃一个无法找到的列表前面的元素,例如。

x > y

删除这些元素后,您可以继续搜索。

对称处理nmcli c | cat -vet 的情况。