比较每个中唯一项目的两个列表

时间:2014-01-27 19:21:27

标签: f# list-comparison

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

我可以从L获取第一项,然后搜索R,如果没有匹配,则将其添加到我的“唯一”集合(Lu)。但这种效率非常低,而且我希望在不久的将来能够处理一些非常大的集合。

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

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

    • 分支1:如果l< r,然后将l添加到Lu并递归,传入Lr :: R

    • 分支2:如果l> r,然后将r添加到Ru并递归,传入l :: LR

    • 分支3:如果l = r,则递归,传入LR

  • 第2步:返回LuRu

我可以编写这个函数,但在我努力之前,我想知道是否已经存在一个可以为我做这个的函数。这似乎是一个不常见的场景,而且我总是宁愿使用现有的解决方案来推动自己的解决方案。

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

1 个答案:

答案 0 :(得分:8)

(我在2小时前写过上面的问题。从那以后,我自己找到了答案。以下是我发现的。)

在集合论中,L中但不在R中的项目的“列表”被称为“L中的R的相对补集”,也称为“L和R的集合理论差异”

(参见维基百科的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|]