Reputation: 4302
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
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