【问题标题】:Haskell run-length encoding functionHaskell 游程编码函数
【发布时间】:2017-10-02 01:02:32
【问题描述】:

此编码函数需要以下输出, code "aaccbbaa" = [('a',2),('c',2),('b',2),('a',2)

但是,这是我的输出。 code "aaccbbaa" = [('a',4),('c',2),('b',2)]

这是我的功能,

code :: Eq a => [a] -> [(a,Int)]
code [] = []
code (x:xs) = [(x, length(filter(==x)(x:xs)))] ++ code(filter (/=x)(xs))

我如何让它重新计算下一个字母出现的时间?

【问题讨论】:

    标签: list haskell encoding integer tuples


    【解决方案1】:

    Data.List中有一个group函数

    code :: Eq a => [a] -> [(a,Int)]
    code = map (\x -> (head x, length x)) . group
    

    λ> code "aaccbbaa"
    [('a',2),('c',2),('b',2),('a',2)]
    

    【讨论】:

    • 这是非常简洁的编码。我刚刚检查了组功能,group "aaccbbaa" 输出["aa","cc","bb","aa"]
    【解决方案2】:

    一个带有辅助函数的foldr 应该足以处理这项工作,如下所示;

    code :: Char -> [(Char,Int)] -> [(Char,Int)]
    code c [(_,0)]    = [(c,1)]
    code c ((x,n):ts) | c == x    = (x,n+1):ts
                      | otherwise = (c,1):(x,n):ts
    
    rle :: String -> [(Char,Int)]
    rle = foldr code [(' ',0)]
    

    根据您的评论接受任何具有Eq 类实例的类型,我们可以简化rle 函数。另一方面,接受的答案涉及 3 个耗时操作,例如 groupmaplength。单次使用没关系,但是如果您将在某些单词或句子上使用此功能数百万次,那么我会建议以下仅在列表中运行一次。

    rle :: Eq a => [a] -> [(a,Int)]
    rle = foldr code []
          where code c []         = [(c,1)]
                code c ((x,n):ts) | c == x    = (x,n+1):ts
                                  | otherwise = (c,1):(x,n):ts
    

    【讨论】:

    • 这也很有效,而且更容易理解。但它改变了原来的数据构造code :: Eq a => [a] -> [(a,Int)]
    • @BCKN 你是对的......我已经根据你的需要更正了代码。它只需要在 O(n) 时间内遍历列表即可完成这项工作。
    猜你喜欢
    • 2023-03-26
    • 2016-03-10
    • 1970-01-01
    • 1970-01-01
    • 2011-11-16
    • 2015-05-27
    • 1970-01-01
    • 1970-01-01
    • 2010-10-15
    相关资源
    最近更新 更多