F#使用函数从列表中删除重复项

时间:2014-01-16 01:03:39

标签: list f#

我想创建一个获取列表的函数,并返回一个包含已删除重复项的列表。

let removedupes list1 =
  let list2 = []
  let rec removeduprec list1 list2 =
    match list1 with
    | [] -> list2
    | head :: tail when mem list2 head = false -> head :: removeduprec tail list2
    | _ -> removeduprec list1.Tail list2
  removeduprec list1 list2

我正在使用这个" mem"函数进入列表并查看值是否已存在,在这种情况下我想继续递归。

let rec mem list x = 
  match list with
  | [] -> false
  | head :: tail -> 
    if x = head then true else mem tail x 

当我测试这段代码时,我得到了

let list1 =  [ 1; 2; 3; 4; 5; 2; 2; 2]
removedups list1;;
val it : int list = [1; 2; 3; 4; 5; 2; 2; 2]

我认为" head :: removeduprec tail list2",但我对f#很新,所以不能完全确定它是如何工作的。

4 个答案:

答案 0 :(得分:6)

我重写了一些逻辑以使事情更简单。问题是您需要在list2创建时添加内容,而不是之后 - 我将::移动到调用内部,如此

let rec mem list x =
  match list with
  | [] -> false
  | head :: tail ->
    if x = head then true else mem tail x

let removedupes list1 =
  let rec removeduprec list1 list2 =
    match list1 with
    | [] -> list2
    | head :: tail when mem list2 head = false -> removeduprec tail (head::list2)
    | h::t -> removeduprec t list2
  removeduprec list1 []

答案 1 :(得分:5)

stackoverflow.com/questions/6842466John's方法的补充;不那么惯用,但快速而明显:

let removeDups is =
    let d = System.Collections.Generic.Dictionary()
    [ for i in is do match d.TryGetValue i with
                     | (false,_) -> d.[i] <- (); yield i
                     | _ -> () ]

它通过

从具有100000个不同值的1000000个元素的列表中删除重复项
 Real: 00:00:00.182, CPU: 00:00:00.171, GC gen0: 14, gen1: 1, gen2: 0

更新:使用HashSet代替Dictionary发表Real: 00:00:00.093, CPU: 00:00:00.093, GC gen0: 2, gen1: 1, gen2: 0 评论,代替Real: 00:00:02.788, CPU: 00:00:02.765, GC gen0: 100, gen1: 21, gen2: 1 提升相同数据的两倍摊销效果:

{{1}}

相反,ildjarn's字面意思与同一测试案例的建议相比,性能 27x

{{1}}

答案 2 :(得分:2)

约翰的回答可能就是你要找的 - 它显示了一种解决问题的惯用功能方式。但是,如果您不想自己实现该功能,最简单的方法是将列表转换为 set (不能包含重复项),然后返回列表:

let list1 = [ 1; 2; 3; 4; 5; 2; 2; 2]
let list2 = List.ofSeq (set list1)

这可能是最短的解决方案:-)与John的版本有一点不同之处在于它不保留列表的原始排序(实际上是对它进行排序)。

答案 3 :(得分:0)

为了完整起见:在F#4.0中,List模块现在具有distinct功能,正好与OP一样。

List.distinct [1; 2; 2; 3; 3; 3];;
val it : int list = [1; 2; 3;]