List 按字符频率对字符串排序
我刚开始使用Haskell,我有以下问题: 我想用一种特殊的方式对字符串排序。所有字符应相邻,它们在结果字符串中的一般位置应取决于它们在原始字符串中出现的频率。例如: “aabcbb”应返回“caabbb” 我的第一个想法是首先对字符串进行排序,然后将字符分组到列表中,比较所述列表的长度,并尝试以某种方式对它们进行排序。 但是,我一直在尝试将字符串转换为字符列表。我已经完成了第一次排序:List 按字符频率对字符串排序,list,haskell,List,Haskell,我刚开始使用Haskell,我有以下问题: 我想用一种特殊的方式对字符串排序。所有字符应相邻,它们在结果字符串中的一般位置应取决于它们在原始字符串中出现的频率。例如: “aabcbb”应返回“caabbb” 我的第一个想法是首先对字符串进行排序,然后将字符分组到列表中,比较所述列表的长度,并尝试以某种方式对它们进行排序。 但是,我一直在尝试将字符串转换为字符列表。我已经完成了第一次排序: listify :: String -> [Char] listify [] = [] listify
listify :: String -> [Char]
listify [] = []
listify (x:xs) = [x] ++ listify isInRest ++ listify notInRest
where
isInRest = [y | y <-xs, y==x]
notInRest = [z | z <-xs, z/=x]
我不会同时使用这两个选项,但如果是这种样式,我不确定如何处理空列表,因为我遇到了以下错误,我不确定如何处理这些错误:
任何帮助都将不胜感激。用于此目的的最自然的数据结构可能是优先级搜索队列。使用其中一个(你可以从黑客那里得到),你可以使用字符作为键,频率计数作为优先级。处理字符串中的所有字符,提高该字符的优先级,然后最终按优先级顺序取出所有字符 使用
psqueues
包
import Data.IntPSQ
import Data.Foldable
buildPSQ :: (Foldable t, Ord p, Num p, Enum a) =>
t a -> IntPSQ p ()
buildPSQ = foldl'
(\q x -> snd $ PSQ.alter
(maybe ((), Just (1,()))
(\(p,_) -> ((), Just (p+1,()))))
(fromEnum x) q)
PSQ.empty
foldrPrio :: Ord p => (Int -> p -> v -> b -> b) -> b -> IntPSQ p v -> b
foldrPrio k n = maybe n (\(c,p,v,r) -> k c p v (foldrPrio k n r)) . PSQ.minView
rebuild :: Enum a => IntPSQ Int t1 -> [a]
rebuild = foldrPrio (\c p _ r -> replicate p (toEnum c) ++ r) []
sortFreq :: (Foldable f, Enum a) => f a -> [a]
sortFreq = rebuild . buildPSQ
所有这些函数都已存在于标准库中。你能做的最简单的事情就是
import Data.Ord
import Data.List
f = concat . sortBy (comparing length) . group . sort
或者,因为length
是O(n),这里有一种更有效的方法:
import Data.Ord
import Data.List
import Control.Arrow
f = concatMap snd . sortBy (comparing fst) . map (length &&& id) . group . sort
而且,String
与[Char]
是一样的
您无法在此处将x
与[]
进行比较
listify :: String -> [Char]
listify (x:xs)
| x == [] = []
| x == "" = ""
因为
x
具有类型Char
,而不是列表。谢谢,我甚至没有想到使用标准库中的函数。然而,我还没有做任何关于功能组合的事情——还有其他方法吗?我特别不明白你是如何使用sortBy的。@skulpt,不知道我是否正确理解你:你想删除这些点吗?如果是这样,您可以编写fx=concat(sortBy(比较长度)(group(sort x))
。或不带括号,但带($)
。不过,只使用函数组合确实更好。是的,这正是我所需要的。看来我刚刚漏掉了括号。谢谢@skulpt,关于sortBy
,你不了解什么?它接收一个函数,该函数决定如何对元素排序比较
构造了这样的函数,定义如下:比较pxy=compare(px)(py)
。在这种情况下,x
和y
是列表,p
是length
,因此我们根据列表的长度进行比较。
listify :: String -> [Char]
listify (x:xs)
| x == [] = []
| x == "" = ""