问题
I have two collections (they happen to be arrays, but it doesn't really matter, I think): L
and R
. They are both sorted and now I want to compare them. I want to end up with two collections: one for each input array containing the items which were not in the other.
I could just take the first item from L
and then search R
and, if there isn't a match, add it to my "unique" collection (Lu
). But that's extremely inefficient, and I am expecting to have some very large collections to process in the near future.
I though about possibly "playing hopscotch":
Step 1: Take two lists,
L
andR
, and compare the head of each list (l :: L
andr :: R
):Branch 1: if
l
<r
, then addl
toLu
and recurse, passing inL
andr :: R
Branch 2: if
l
>r
, then addr
toRu
and recurse, passing inl :: L
andR
Branch 3: if
l
=r
, then recurse, passing inL
andR
Step 2: return
Lu
andRu
I can write this function, but before I put in the effort I was wondering if a function already exists which can do this for me. It seems like a not-to-uncommon scenario, and I'd always rather use an existing solution to rolling my own.
(Also, if there's a more recognizable name for this algorithm, I'd like to know what it's called.)
回答1:
(I wrote the question above about 2 hours ago. Since then, I found the answer on my own. The following is what I discovered.)
In set theory, the "list" of items in L but not in R is known as "the relative complement of R in L", also known as "set-theoretic difference of L and R"
(See Wikipedia's Complement (set theory) article)

F#, being a mathematical language, has this concept baked right in to it's Core library. First, you need to build your collections as sets:
// 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
Now you can call the "difference" function and quickly get the relative complement for each array:
let Lu = Set.difference L R |> Set.toArray
let Ru = Set.difference R L |> Set.toArray
> val Lu : int [] = [|1|]
> val Ru : int [] = [|4|]
There's also a shorter syntax. The Set type has overloaded the minus operator. Set.difference just subtracts the second parameter from the first, so you can actually just use the following:
let Lu = L - R |> Set.toArray
let Ru = R - L |> Set.toArray
> val Lu : int [] = [|1|]
> val Ru : int [] = [|4|]
来源:https://stackoverflow.com/questions/21389733/comparing-two-lists-for-unique-items-in-each