Haskell:列表理解/哈希表条目

时间:2012-11-01 02:42:44

标签: haskell hashtable list-comprehension

我正在尝试根据长度将一堆单词放入哈希表中。这些单词存储在

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

非常感谢任何帮助!

干杯

2 个答案:

答案 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]