是否有一种有效的方法将值插入Data.Set
,同时检查该值是否已经是该集合的成员?
如果没有,是否有任何特殊原因使用containers
库中当前的集合实现无法编写这样的函数?
答案 0 :(得分:7)
您可以利用O(log n)
为size
的事实,O(1)
的复杂性来执行此操作,并在之前和之后进行比较:
-- | Inserts a value into the Set. If the value was not already in the set,
-- | then True is returned, otherwise False
insertIfMissing :: Ord a => a -> Set a -> (Set a, Bool)
insertIfMissing a s = (newSet, missing)
where
newSet = Set.insert a s
oldSize = Set.size s
newSize = Set.size newSet
missing = oldSize < newSize
如果你对它是否已经存在并不感兴趣,那么由于懒惰,这不应该计算missing
部分。
答案 1 :(得分:2)
实际上可以通过稍微改变Set.insert
函数来编写这样的函数。我决定返回Maybe (Set a)
,因此如果元素不存在,该函数只会创建一个新的Set
。编写一个(Bool, Set a)
作为返回类型的函数也是可能的。
insertMember :: Ord a => a -> Set a -> Maybe (Set a)
insertMember = go
where
go :: Ord a => a -> Set a -> Maybe (Set a)
STRICT_1_OF_2(go)
go x Tip = Just $ singleton x
go x (Bin sz y l r) = case compare x y of
LT -> do
l' <- go x l
return $ balanceL y l' r
GT -> do
r' <- go x r
return $ balanceR y l
EQ -> Nothing