合并F#中的两个列表

时间:2015-02-23 15:58:22

标签: f#

我编写了这个函数,它将两个列表合并在一起,但由于我对函数式编程相当新,我想知道是否有更好(更简单)的方法呢?

let a = ["a"; "b"; "c"]
let b = ["d"; "b"; "a"]

let merge a b =
    // take all a and add b
    List.fold (fun acc elem -> 
                     let alreadyContains = acc |> List.exists (fun item -> item = elem)
                     if alreadyContains = true then
                        acc
                     else 
                        elem :: acc |> List.rev
                     ) b a                

let test = merge a b 

预期结果是:[" a&#34 ;; " B&#34 ;; " C&#34 ;; " d"],我还原了列表以保留原始订单。我以为我可以使用List.foldBack(并删除List.rev)来实现相同的效果,但它会导致错误:

类型不匹配。期待一个     '一个
但给了一个     '列表
在统一' a'和''列表'

使用foldBack时为什么会有区别?

2 个答案:

答案 0 :(得分:7)

您可以使用以下内容

let merge a b =
    a @ b
    |> Seq.distinct
    |> List.ofSeq

请注意,这将保留顺序并删除所有重复项。

在F#4.0中,这将简化为

let merge a b = a @ b |> List.distinct

答案 1 :(得分:2)

如果我想以类似于原始版本的方式编写它(使用fold),那么我要做的主要改变是将List.rev移到函数之外(你是每次添加新元素时都会调用List.rev,如果您要添加偶数元素,则会出错!)

因此,与您的解决方案非常相似的解决方案是:

let merge a b =
  (b, a) 
  ||> List.fold (fun acc elem -> 
        let alreadyContains = acc |> List.exists (fun item -> item = elem)
        if alreadyContains = true then acc
        else elem :: acc)   
  |> List.rev

这使用双管道运算符||>将两个参数传递给fold函数(这不是必需的,但我发现它更好一些),然后将结果传递给{{1 }}