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

JDB*_*JDB 5 f# list-comparison

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

我可以从第一个项目中L搜索R,然后搜索,如果没有匹配,则将其添加到我的"唯一"集合(Lu).但这是非常低效的,我期待在不久的将来有一些非常大的集合进行处理.

我虽然可能"玩跳房子":

  • 第1步:获取两个列表,L然后R比较每个列表的头部(l :: Lr :: R):

    • 分支1:如果l< r,再加入lLu和递归,传递Lr :: R

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

    • 分支3:if l= r,然后递归,传入LR

  • 第2步:返回LuRu

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

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

JDB*_*JDB 8

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

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

(参见维基百科的补语(集合论)文章)

作为一种数学语言的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
Run Code Online (Sandbox Code Playgroud)

现在你可以调用"差异"函数并快速获得每个数组的相对补码:

let Lu = Set.difference L R |> Set.toArray
let Ru = Set.difference R L |> Set.toArray
Run Code Online (Sandbox Code Playgroud)
> val Lu : int [] = [|1|]
> val Ru : int [] = [|4|]
Run Code Online (Sandbox Code Playgroud)

语法也更短.Set类型重载了减号运算符.Set.difference只需从第一个参数中减去第二个参数,所以您实际上可以使用以下参数:

let Lu = L - R |> Set.toArray
let Ru = R - L |> Set.toArray
Run Code Online (Sandbox Code Playgroud)
> val Lu : int [] = [|1|]
> val Ru : int [] = [|4|]
Run Code Online (Sandbox Code Playgroud)

  • 更简洁地说,你可以这样做:`set [1; 2; 3] - 设置[2; 3; 4]`.`set`函数适用于任何序列(列表,数组等). (5认同)