【问题标题】:Haskell function sort input list then do stuff with sorted listHaskell 函数对输入列表进行排序,然后对排序列表进行处理
【发布时间】:2016-09-27 19:56:49
【问题描述】:

短版:

我想对一个列表进行排序,然后对排序后的列表执行过滤/提取数据以形成一个新列表的操作,这一切都在一个函数中。

长版:

我正在使用 these lessons 自学 Haskell。我目前在Homework 2练习5。

我需要编写一个函数whatWentWrong,它接受一个未排序 LogMessages 列表并返回一个字符串列表。字符串是用Error构造的LogMessage的String部分,其中Error代码> 50。它们应该按LogMessage的TimeStamp部分排序。

我有一个为 whatWentWrong 编写的函数,它可以工作,但它真的很慢(你会明白为什么)。

whatWentWrong :: [LogMessage] -> [String]
whatWentWrong [] = []
whatWentWrong ys@((LogMessage (Error code) _ msg):xs)
    | ys /= inOrder (build ys)
      = whatWentWrong (inOrder (build ys))
    | code > 50
      = [msg] ++ whatWentWrong xs
    | otherwise
      = whatWentWrong xs
whatWentWrong (_:xs) = [] ++ whatWentWrong xs

函数inOrder (build x) 将返回 x 的排序版本(其中 x 是 LogMessage 列表)。显然,我必须在使用whatWentWrong 开始处理列表之前对列表进行排序,或者我必须过滤掉所有不相关的消息(不是错误或错误代码不超过 50 的消息),排序,然后抓住每一根弦。

如果我不遵循这个例子,我会定义另一个函数或其他东西,或者只是发送whatWentWrong 一个已经排序的列表。但我想这样做是有原因的(我想不通)。

不管怎样,我做了什么,为什么程序这么慢是这样的: ys /= inOrder (build ys) 行正在检查 LogMessage 列表是否已排序每次遇到与错误模式匹配的 LogMessage 时,即使在第一次检查失败后,列表已排序好.

这是我能想到的唯一方法。真的,我想对它进行一次排序,但我不知道如何使用我的排序函数使函数对列表进行排序,然后不再执行该步骤。我显然没有正确考虑这一点,任何帮助表示赞赏。谢谢。

【问题讨论】:

    标签: list sorting haskell


    【解决方案1】:

    你真的只需要一个单行列表理解:

    whatWentWrong xs = [ msg | (LogMessage (Error code) _ msg) <- inOrder (build xs), code > 50]
    

    如果您正在对列表进行排序以查看列表是否已排序,那么您也可以直接在已排序的列表上工作。完成此操作后,列表解析将自动过滤掉不匹配的元素,code &gt; 50 过滤其余元素。


    如果您想修复当前代码作为练习,您只需要定义一个假定其输入已排序的辅助函数。

    whatWentWrong :: [LogMessage] -> [String]
    whatWentWrong ys = www (inOrder (build ys))
                       where www [] = []
                             www ((LogMessage (Error code) _ msg):xs) | code > 50 = msg : www xs
                                                                      | otherwise = www xs
                             www (_:xs) = www xs
    

    但是,您应该认识到 www 是 一个map 和一个filter

    whatWentWrong ys = map f $ filter p (inOrder (build ys))
                       where p (LogMessage (Error code) _ _) = code > 50
                             p _ = False
                             f (LogMessage _ _ msg) = msg
    

    或者,无点风格

    whatWentWrong = map f . filter p . inOrder . build
                    where p (LogMessage (Error code) _ _) = code > 50
                          p _ = False
                          f (LogMessage _ _ msg) = msg
    

    【讨论】:

    • 哇,太简单了。我还没有列出理解,但是告诉我我是否有这个权利:如果它与 LogMessage 等模式和code &gt; 50 匹配,这将为排序列表xs 的每个元素创建一个msg 列表。与我的功能相比,它的速度也快得惊人。
    • 没错;模式匹配过滤掉InfoWarning 消息,而守卫过滤掉低编号错误。
    猜你喜欢
    • 2017-09-28
    • 1970-01-01
    • 2018-08-16
    • 2012-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-03
    • 1970-01-01
    相关资源
    最近更新 更多