我正在尝试根据长度将一堆单词放入哈希表中。这些单词存储在
中data Entry = Entry {word :: String, length :: Int} deriving Show
现在,我已经将所有单词存储在“条目”中,这是一个条目列表。然后,我的哈希表定义如下:
type Hash = [Run]
type Run = [Entry]
现在我正在试图弄清楚如何将条目输入哈希表。以下是我目前的尝试
maxL = maximum [length e | e <- entries]
runs = [r | r <- [e | e <- entries, length e == i]] where i = [1..maxL]
编译器显然告诉我Int不能与[Int]相比,但我不知道怎么说
e | e <- entries, e has length i
非常感谢任何帮助!
干杯
答案 0 :(得分:2)
您正在寻找Data.List
的{{3}}功能。您有一个字符串列表,您希望按其长度分组。 groupBy
函数的类型为(a -> a -> Bool) -> [a] -> [[a]]
。第二个参数是您的输入列表,第一个是您需要编写的函数,它应该使用两个字符串并比较它们的长度。它将返回一个字符串列表列表,其中每个子列表将包含相等长度的字符串。
顺便说一下,如果你想简洁地写一下,请查看来自Data.Function
的{{3}}组合子。
答案 1 :(得分:2)
您的代码几乎没问题:
maxL = maximum [length e | e <- entries]
runs = [r | r <- [e | e <- entries, length e == i]] where i = [1..maxL]
除了where
不起作用。它不是foreach
的同义词;但对于let
:
runs = let i = [1..maxL]
in [r | r <- [e | e <- entries, length e == i]]
因此,length e
是一个整数,但i
是[1..maxL]
,它是一个整数列表。您打算让i
逐个接受[1..maxL]
中的值,这是通过列表理解中<-
绑定完成的:
runs = [ [r | r <- [e | e <- entries, length e == i]] | i <- [1..maxL]]
现在,[r | r <- xs]
与xs
相同,因此它变为
runs = [ [e | e <- entries, length e == i] | i <- [1..maxL]]
使用“标准”功能,将其写为
import Data.List (sortBy)
import Data.Ord (comparing)
runs = group $ sortBy (comparing length) entries
它在算法上也更好。虽然,对于不存在的长度,它不会有空运行,所以两者并不是严格等价的。但是可以通过结果的另一个O(n)
传递修复,
-- mapAccumL :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])
runs' = snd $ mapAccumL
(\a@ ~((k,g):t) i-> if null a || i<k then (a,[]) else (t,g))
[ (length $ head g, g) | g<- runs]
[ 1..maxL]