Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Performance 创建集合中所有元素对的数据集的最有效方法?_Performance_Haskell - Fatal编程技术网

Performance 创建集合中所有元素对的数据集的最有效方法?

Performance 创建集合中所有元素对的数据集的最有效方法?,performance,haskell,Performance,Haskell,给定一个包含任意数量任意类型元素的任意集合,例如 mySet1 = Set.fromList [1,2,3,4] 或 或 对于某些数据构造函数A、B、C、D 生成所有无序元素对集合的计算效率最高的方法是给定集合?即 setPairs mySet1 == Set.fromList [(1,2),(1,3),(1,4),(2,3),(2,4),(3,4)] 或 或 我最初天真的猜测是: setPairs s = fst $ Set.fold (\e (pairAcc, elements

给定一个包含任意数量任意类型元素的任意集合,例如

mySet1 = Set.fromList [1,2,3,4]

对于某些数据构造函数A、B、C、D

生成所有无序元素对集合的计算效率最高的方法是给定集合?即

setPairs mySet1 == Set.fromList [(1,2),(1,3),(1,4),(2,3),(2,4),(3,4)]


我最初天真的猜测是:

setPairs s = fst $ Set.fold
    (\e (pairAcc, elementsLeft) ->
        ( Set.fold
              (\e2 pairAcc2 ->
                  Set.insert (e2, e) pairAcc2
              ) pairAcc $ Set.delete e elementsLeft
        , Set.delete e elementsLeft )
    ) (Set.empty, s) s

但这肯定不是最好的解决方案吗?

首先,您需要生成所有集合<来自控件的代码>复制项。Monad帮助完成此操作

λ> replicateM 2 [1..4]
[[1,1],[1,2],[1,3],[1,4],[2,1],[2,2],[2,3],[2,4],[3,1],[3,2],[3,3],[3,4],[4,1],[4,2],[4,3],[4,4]]
然后需要过滤对,其中第二个元素大于第一个元素

λ> filter (\[x,y] -> x < y)  $ replicateM 2 [1 .. 4]
[[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]]
所以,如果我答对了你的问题,你可以使用
pairs mySet
,其中pairs生成
mySet
的所有无序对的列表

这是你想要的吗

UPD

可以使用更清晰、更快速的技术来创建这样的子列表,因此这里是另一个
对的实例:

import Data.Set
import Control.Monad
import Data.List

mySet = Data.Set.fromList [1,2,3,4]

--setOfPairs = Data.Set.fromList [(1,2),(1,3),(1,4),(2,3),(2,4),(3,4)]
setOfPairs = Data.Set.fromList $ pairs mySet

pairs :: Ord a => Set a -> [(a,a)]
pairs x = Data.List.map (\[x,y] -> (x,y)) $ Data.List.filter (\[x,y] -> x < y) $ replicateM 2 $ toList x
pairs :: Ord a => Set a -> [(a,a)]
pairs set = [(x,y) | let list = toList set, x <- list, y <- list, x < y]
pairs::Ord a=>设置a->[(a,a)]

pairs set=[(x,y)| let list=toList set,x因此,这里是第一次尝试使用列表来回转换的解决方案。同样,我不确定这是实现这一点的最快方法,但我知道,在集合上进行迭代并不是非常有效

import Data.List
import qualified Data.Set as S

pairs :: S.Set String -> S.Set (String,String)
pairs s = S.fromList $ foldl' (\st e -> (zip l e) ++ st) [] ls
          where (l:ls) = tails $ S.toList s
通过将拉链折叠到尾巴上,您可以获得一种很好且有效的方法来创建无序对集。然而,本能鼓励我,可能会有一种更优雅的单体过滤器或折叠解决方案。我会继续思考

[编辑]

因此,这里是一个不需要收费表的更快的解决方案(但不是因为功率集的大小)

import Data.List
import qualified Data.Set as S
import qualified Data.Foldable as F

pairs :: (Ord a) => S.Set a -> S.Set (a,a)
pairs s = S.fromList $ foldl two [] $ F.foldlM (\st e -> [[e]++st,st]) [] s
          where two st (x:xa:[]) = (x,xa) : st
                two st _ = st

在一元列表上使用幂集解决方案来构建幂集,然后过滤掉幂集对。如有必要,我可以更详细地介绍。

基准测试可能会证明我错了,但我的怀疑是,保持在集表示中是没有好处的。您将需要O(n^2)不管怎样,因为这是输出的大小。关键的优势是生成列表,这样您就可以使用对
s.fromDistinctAscList
的调用,这样构建集合本身只需花费O(n)

以下内容非常简洁,保留了相当多的共享,通常是我能想象到的最简单、最直接和直观的解决方案

pairs s = S.fromDistinctAscList . concat $ zipWith zip (map (cycle . take 1) ts) (drop 1 ts)
   where ts = tails $ S.toList s

编辑

更短/更清晰(不确定性能,但可能同样好/更好):


对s=s.fromDistinctAscList[(x,y)|(x:xt)考虑这一点最简单的方法是列表理解,答案几乎是自己写的……是的,我可以看到这是用集合完成的,但它可能不会像filterM或列表理解解决方案那样优雅。转换为列表是一种选项,还是列表航路点使解决方案对您不可行?@Erik Hinton:如果列表提供了最快的方法,那么转换到列表就可以了。感谢您提供的详细答案。不幸的是,这对字符串集不起作用,因为它们不在Ord中。请给出一些示例,说明您对
setOfPairs
的期望值。对不起,当然字符串和Ord中的任何数据类型的元素一样在Ord中一套。我很抱歉。但是转换到列表真的是最快的方法吗?我只是一个初学者,没有比较一些算法和数据类型的经验。我所能说的是-转换到列表是解决您的问题的最简单的方法。我的本能是同意您的看法。唯一关心的是是否有一些伟大的问题
toList
中的开销。但是,我怀疑它是否会非常昂贵。
toList
被定义为折叠,这是直接定义的。我想这个解决方案比其他解决方案使用更少的中间内存,因为它尽可能地流式处理。最后一组使用的内存当然是going无论如何都要花费相同的成本。我做了一些基准测试。上面给出的两种解决方案都是迄今为止给出的解决方案中最快的。使用列表理解的较短版本对于大集合更快,但对于小集合则更慢。谢谢!在快速基准测试中,使用toList的解决方案比不使用toList的解决方案快得多。Since功率集的大小随给定集的大小呈指数增长,此解决方案的时间消耗也是如此。干杯,啊,非常好。当有疑问时,请始终相信基准。干杯,
import Data.Set
import Control.Monad
import Data.List

mySet = Data.Set.fromList [1,2,3,4]

--setOfPairs = Data.Set.fromList [(1,2),(1,3),(1,4),(2,3),(2,4),(3,4)]
setOfPairs = Data.Set.fromList $ pairs mySet

pairs :: Ord a => Set a -> [(a,a)]
pairs x = Data.List.map (\[x,y] -> (x,y)) $ Data.List.filter (\[x,y] -> x < y) $ replicateM 2 $ toList x
pairs :: Ord a => Set a -> [(a,a)]
pairs set = [(x,y) | let list = toList set, x <- list, y <- list, x < y]
import Data.List
import qualified Data.Set as S

pairs :: S.Set String -> S.Set (String,String)
pairs s = S.fromList $ foldl' (\st e -> (zip l e) ++ st) [] ls
          where (l:ls) = tails $ S.toList s
import Data.List
import qualified Data.Set as S
import qualified Data.Foldable as F

pairs :: (Ord a) => S.Set a -> S.Set (a,a)
pairs s = S.fromList $ foldl two [] $ F.foldlM (\st e -> [[e]++st,st]) [] s
          where two st (x:xa:[]) = (x,xa) : st
                two st _ = st
pairs s = S.fromDistinctAscList . concat $ zipWith zip (map (cycle . take 1) ts) (drop 1 ts)
   where ts = tails $ S.toList s
pairs s = S.fromDistinctAscList [(x,y) | (x:xt) <- tails (S.toList s), y <- xt]