插入Data.Set并检查元素是否同时存在

时间:2014-09-13 20:08:21

标签: haskell

是否有一种有效的方法将值插入Data.Set,同时检查该值是否已经是该集合的成员?

如果没有,是否有任何特殊原因使用containers库中当前的集合实现无法编写这样的函数?

2 个答案:

答案 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