使用有序的Int压缩一个Set

时间:2014-07-24 06:38:52

标签: haskell

Haskell中有zip Set的方式,而不必先将其转换为List吗?

我想要一个从给定边缘数据创建一组顶点的函数。顶点基本上是一对索引及其数据。

data Vertex a = Vertex { idx::Int, cont::a }

toVertexSet :: S.Set String -> S.Set (Vertex String)
toVertexSet = undefined

toStringSet:: [(String, String, Int)] -> S.Set String
toStringSet = foldl insertToSet S.empty where
    insertToSet set (vfrom, vto, _) =
        case (S.member vfrom set, S.member vto set) of
            (True, True) -> set
            (True, False) -> S.insert vto set
            (False, True) -> S.insert vfrom set 
            (False, False) -> S.insert vto (S.insert vfrom set)

基本上我希望toVertexSet将每个String与唯一Int配对作为索引,从1开始排列到集合的大小,将其转换为一组顶点。有没有更好的方法来做到这一点,而不必先将集合转换回List?

2 个答案:

答案 0 :(得分:6)

集合是可折叠的,因此您可以使用折叠:

import Data.Foldable (foldl')

data Vertex a = Vertex { idx::Int, cont::a } deriving (Eq, Ord)

toVertexSet :: S.Set String -> S.Set (Vertex String)
toVertexSet = snd . foldl' (\(i, vs) s -> (i+1, S.insert Vertex { idx = i, cont  = s } vs)) (1, S.empty)

答案 1 :(得分:2)

您不需要zip来实现这一点,我目前的解决方案是根据其内容在Eq上派生Vertex,以便它可以直接存储在Set中,并且使用带有最后插入索引的辅助函数作为附加参数。不过,我失去了优雅的褶皱。

instance (Eq a) => Eq (Vertex a) where
    v1 == v2 = cont v1 == cont v2

instance (Eq a, Ord a) => Ord (Vertex a) where 
    v1 `compare` v2 = cont v1 `compare` cont v2

toVertexSet:: [(String, String, Int)] -> S.Set (Vertex String)
toVertexSet = insertToSet 0 S.empty where
    insertToSet _ set [] = set 
    insertToSet ix set ((vfrom, vto, _):rest) =
        let newVertex  = Vertex ix
            nvfrom     = newVertex vfrom
            nvto       = newVertex vto
            incrOne (Vertex i m) = Vertex (i + 1) m
        in case (S.member nvfrom set, S.member nvto set) of
            (True, True) -> insertToSet ix set rest
            (True, False) -> insertToSet (ix + 1) (S.insert nvto set) rest
            (False, True) -> insertToSet (ix + 1) (S.insert nvfrom set) rest
            (False, False) -> insertToSet (ix + 2) (S.insert (incrOne nvfrom) 
                                (S.insert nvto set)) rest