Jamie Dixon
Jamie Dixon

Reputation: 4302

Finding the difference between two arrays in FSharp

I have two arrays where I want to find the elements from the second array that are not in the first array.

I wrote the following code:

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)

But I am wondering if there is something that is more idiomatic to FSharp.

Thanks in advance

Upvotes: 4

Views: 1350

Answers (1)

Tomas Petricek
Tomas Petricek

Reputation: 243061

If you do not care about duplicates, then you could write this using F# sets:

// 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)

In both cases, you get back a new set<int>, which is also a seq<int>, so you can iterate over it or turn it back into array using Array.ofSeq.

If you want to keep duplicates (if there are duplicates in array1, then return the element multiple times), then I think what you have is good. If you wanted to compare multiple arrays against one, then it would make sense to turn array0 into a dictionary for more efficient lookup:

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

The conversion to set has some cost, but it reduces the lookup time. So, depending on how you use this & what is the size of the arrays, this will have different performance characteristics. But the code looks nicer, so this would be my default choice.

Upvotes: 6

Related Questions