Skip to content

difference and differenceWith could be much faster #364

@sjakobi

Description

@sjakobi

Similarly to intersection and friends (#225), the current implementations of difference[With] leave a lot of performance on the table.

It should be relatively easy to optimize the insertions into the result map with the suggestions from #225 (comment).

Additional gains should be possible by traversing the two trees directly.

-- | /O(n*log m)/ Difference of two maps. Return elements of the first map
-- not existing in the second.
difference :: (Eq k, Hashable k) => HashMap k v -> HashMap k w -> HashMap k v
difference a b = foldlWithKey' go empty a
where
go m k v = case lookup k b of
Nothing -> insert k v m
_ -> m
{-# INLINABLE difference #-}
-- | /O(n*log m)/ Difference with a combining function. When two equal keys are
-- encountered, the combining function is applied to the values of these keys.
-- If it returns 'Nothing', the element is discarded (proper set difference). If
-- it returns (@'Just' y@), the element is updated with a new value @y@.
differenceWith :: (Eq k, Hashable k) => (v -> w -> Maybe v) -> HashMap k v -> HashMap k w -> HashMap k v
differenceWith f a b = foldlWithKey' go empty a
where
go m k v = case lookup k b of
Nothing -> insert k v m
Just w -> maybe m (\y -> insert k y m) (f v w)
{-# INLINABLE differenceWith #-}

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions