我有一组由Data.Set
的Set (Set a)
类型代表的集合。
我想结合其交集不为空的所有成员集。
等效地,如果 x 和 y <,我希望图表的组件有一个连接 x 和 y 的边缘/ em>在同一个Set中。
示例:
-- import qualified Data.Set as S
ghci> f $ S.fromList [S.fromList [1,2], S.fromList [2,3], S.fromList [5]]
> S.fromList [S.fromList [1,2,3], S.fromList [5]]
ghci> f $ S.fromList [ S.fromList [1,2], S.fromList [2,3], S.fromList [3,4] ]
> S.fromlist [ S.fromList [1,2,3,4] ]
什么是优雅的性能解决方案?
答案 0 :(得分:5)
对于要合并的大量集合,您希望使用union find算法。
你可以在这里找到实现联合查找算法的Haskell代码:
https://github.com/erantapaa/union-find-example
此外,对于Int集合,您将要使用Data.IntSet
- 效率更高。
之前我编写了以下内容,它不会传递合并集合:
这是一个折叠:
import qualified Data.Set as S
import Data.List (foldl')
mergeSets as = foldl' merge [] as
-- merge one set into a list of sets
merge [] a = [a]
merge (b:bs) a = if S.null (S.intersection a b)
then b : merge bs a
else (S.union a b) : bs
test = mergeSets [ S.fromList [1,2], S.fromList [2,3], S.fromList [5] ]
答案 1 :(得分:2)
<div id="div1"></div>
<div id="div2">
<div id="div3"><img src="myurl" id="image" onclick="change(this);"/></div>
</div>
构造Set (Set a)
简单的折叠不适用于复杂的import qualified Data.Set as S
innerUnions :: Ord a => S.Set (S.Set a) -> S.Set (S.Set a)
innerUnions = innerUnion' S.empty
where
innerUnion' :: Ord a => S.Set (S.Set a) -> S.Set (S.Set a) -> S.Set (S.Set a)
innerUnion' seta setb
| S.null setb = seta
| otherwise = innerUnion' (S.insert unioned seta) stripped
where
(unioned,stripped) = S.foldl f (minElem, setb') setb'
minElem = S.findMin setb
setb' = S.deleteMin setb
f :: Ord a => (S.Set a, S.Set (S.Set a)) -> S.Set a -> (S.Set a, S.Set (S.Set a))
f (x,xs) y
| (not . S.null) (x `S.intersection` y) = (x `S.union` y, S.delete y xs)
| otherwise = (x,xs)
构造。简单的折叠会产生不正确的结果
示例:强>
Set (Set a)
正确转型:
ghci> simpleFold $ S.fromList
[ S.fromList [1,2], S.fromList [2,3], S.fromList [3,4]
, S.fromList [5], S.fromList [5,6], S.fromList [6]
, S.fromList [8,9], S.fromList [0,9], S.fromList [0,1]]
> fromList [fromList [0,1,2,3,4],fromList [5,6],fromList [0,8,9]]
这是因为我们必须在构建结果集时使用输入集。折叠期间折叠无法访问整个输入集,只能在给定时间访问输入集的单个元素。这意味着转换函数无法正确地使用输入集中的元素,因为它无法访问输入集的所有元素。我们需要手动编写一个更复杂的折叠,同时消耗输入集并构建结果集。
上面的ghci> innerUnions $ S.fromList
[ S.fromList [1,2], S.fromList [2,3], S.fromList [3,4]
, S.fromList [5], S.fromList [5,6], S.fromList [6]
, S.fromList [8,9], S.fromList [0,9], S.fromList [0,1]]
> fromList [fromList [0,1,2,3,4,8,9],fromList [5,6]]
函数执行此同时消费&amp;应用于折叠时的结构。