在FSharp中查找两个数组之间的差异

4
我有两个数组,想要找出第二个数组中不在第一个数组中的元素。
我写了以下代码:
let array0 = [|"A";"B";"C"|]
let array1 = [|"B";"D";"E"|]

let inZero letter = 
    array0 |> Array.tryFind(fun l -> if l = letter then true else false)

array1|> Array.filter(fun l -> inZero(l).IsSome)

但我想知道是否有更符合FSharp惯用语的东西。

提前感谢。


此外,建议使用Enumerable.Except的已删除答案也听起来像一个不错的选择。 - Tomas Petricek
1
如果你能等到 F# 4.0(或可能是 4.1),那么 Array.Except 的拉取请求已经开放了 :) https://github.com/Microsoft/visualfsharp/pull/253 - Patrick McDonald
1个回答

6

如果您不关心重复项,那么您可以使用 F# 集合来编写此代码:

// Elements that are in array1, but not in array0
set array1 - set array0

// Elements that are in both arrays (which is what your sample returns)
Set.intersect (set array1) (set array0)

在这两种情况下,你得到一个新的set<int>,它也是一个seq<int>,所以你可以迭代它或使用Array.ofSeq将其转换回数组。
如果你想保留重复项(如果array1中有重复项,则返回元素多次),那么我认为你已经做得很好了。如果你想将多个数组与一个数组进行比较,那么将array0转换为字典以进行更有效的查找就有意义了。
let inZero =
  let set0 = set array0
  set0.Contains

// Elements from array1 that are also in array0 (returns multiple
// copies of the same element if it appears repeatedly in array1)
array1 |> Array.filter inZero

将数组转化为集合会有一定的开销,但可以减少查找时间。因此,根据您使用的方式以及数组的大小,这将具有不同的性能特征。但代码看起来更好,因此这将是我的默认选择。


我本意是使用 .IsNone 来返回不在两者中的内容。请使用 not Set.intersect?。 - Jamie Dixon
集合差(set array1 - set array0)应该给出在array1中但不在array0中的元素(相交操作是使用IsSome实现的)。 - Tomas Petricek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接