2014-01-27 114 views
5

独特的项目我有两个集合(它们恰好是数组,但它并不重要,我认为):LR。他们都是排序的,现在我想比较他们。我想最终得到两个集合:一个用于包含不在另一个中的项目的每个输入数组。比较两个列表中每个

我可以从L中取出第一项,然后搜索R,如果没有匹配项,将它添加到我的“唯一”集合(Lu)中。但这是非常低效的,而且我预计在不久的将来会有一些非常大的集合进行处理。

我虽然关于可能 “玩跳房子”:

  • 第1步:取两个列表,LR,并比较每个列表(l :: Lr :: R)头:

    • 科1:如果l < r,然后加lLu并递归,传入Lr :: R

    • 分支2:如果l>r,再加入rRu和递归,传入l :: LR

    • 科3:如果l = r,然后递归,传递LR

  • 第2步:返回Lu a第二Ru

我可以写这个功能,但我付出努力之前,我在想,如果一个函数已经存在,可以帮我这个忙。这似乎是一个不常见的情况,我总是宁愿使用现有的解决方案来滚动我自己的。

(另外,如果有一个更容易识别的名字为这个算法,我想知道它叫什么。)

回答

8

(我写上面约2小时前的问题。从那时起,我发现回答我自己的,下面是我发现的。)

在集合论中,以L而不是R中被称为“R,L的相对补”项目的“清单”,也称为“L和R的集合理论差异”

(参见Wiki pedia的Complement (set theory)文章)

F#,作为一个数学语言,有这个概念就在它的核心库出炉。首先,你需要建立自己的收藏品作为集:

// example arrays: 
let arr1 = [| 1; 2; 3 |] 
let arr2 = [| 2; 3; 4 |] 

// build the L and R sets 
let L = set arr1 
let R = set arr2 

现在,您可以拨打“差异化”功能,并迅速得到了相对补为每个阵列:

let Lu = Set.difference L R |> Set.toArray 
let Ru = Set.difference R L |> Set.toArray 
> val Lu : int [] = [|1|] 
> val Ru : int [] = [|4|] 

还有一个更短的语法。 Set类型有overloaded the minus operatorSet.difference只是减去从第一第二个参数,这样可以真正使用以下命令:

let Lu = L - R |> Set.toArray 
let Ru = R - L |> Set.toArray 
> val Lu : int [] = [|1|] 
> val Ru : int [] = [|4|] 
+5

更简洁,你可以这样做:'[1; 2; 3] - 设置[2; 3; 4]'。 'set'函数适用于任何序列(列表,数组等)。 – Daniel

+0

很棒的发现!感谢你的分享! – Martin

+0

哦,而不是自己折叠数组,你可以使用'[| 1; 2; 3; |] |> Set.ofArray' - 与seq和list一起工作的函数也存在。 – Martin