【问题标题】:Comparing two lists for unique items in each比较两个列表中每个列表中的唯一项目
【发布时间】:2014-01-27 19:21:27
【问题描述】:

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

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

我想可能会“玩跳房子”:

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

    • 分支1:如果lr,则将l添加到Lu并递归,传入Lr :: R

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

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

  • 第二步:返回LuRu

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

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

【问题讨论】:

    标签: f# list-comparison


    【解决方案1】:

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

    在集合论中,L中而不是R中的项目的“列表”称为“R在L中的相对补集”,也称为“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|]
    

    【讨论】:

    • 更简洁,你可以这样做:set [1; 2; 3] - set [2; 3; 4]set 函数适用于任何序列(列表、数组等)。
    • 很棒的发现!谢谢分享!
    • 哦,您也可以使用[|1; 2; 3;|] |> Set.ofArray,而不是自己折叠数组 - 也存在与 seq 和 list 一起使用的函数。
    • @Daniel - 太棒了。随着时间的流逝,F# 变得越来越酷。
    猜你喜欢
    • 2016-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多